C++ lock

在多线程编程中被广泛使用, 通过能够保证临界区的数据顺序访问. 在使用的过程中, 最容易现的问题是: 死锁. 幸好C++为我们提供了很好的机制尽量避免死锁的出现.

std::lock_guard 是一个RAII风格的锁, 在离开作用域范围时, 自动释放锁. 下面直接看一个例子:

#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
#include <cassert>

static int g_index = 0;
static const int CNT = 1000;
std::mutex g_mutex;

static void _inc(void) {
    for (int i = 0; i < CNT; i++) {
        const std::lock_guard<std::mutex> lock(g_mutex);
        ++g_index;
    }
}

int main(void) {
    std::vector<std::thread> v_th;

    for (int i = 0; i < 10; i++) {
        std::thread t(_inc);
        v_th.push_back(std::move(t));
    }

    for (auto &t : v_th) {
        t.join();
    }

    assert(g_index == 1000 * 10);
    return 0;
}

std::unique_lock是一个功能更全的. 支持延迟锁, 时间锁, 互斥锁, 递归锁, 还能支持转移的所有权等功能. 下面也看一个例子:

#include <cassert>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>

static const int CNT = 1000;
static int g_inc_index = 0;
static int g_dec_index = 0;
std::mutex g_inc_mutex;
std::mutex g_dec_mutex;

static void _run(void) {
    for (int i = 0; i < CNT; i++) {
        std::unique_lock<std::mutex> inc_lock(g_inc_mutex, std::defer_lock);
        std::unique_lock<std::mutex> dec_lock(g_dec_mutex, std::defer_lock);

        std::lock(inc_lock, dec_lock);
        ++g_inc_index;
        --g_dec_index;
    }
}

int main(void) {
    std::vector<std::thread> v_th;

    for (int i = 0; i < 10; i++) {
        v_th.emplace_back(_run);
    }

    for (auto &t : v_th) {
        t.join();
    }

    assert(g_inc_index == -g_dec_index);
    return 0;
}

std::scoped_lockstd::lock_guard类似, 不同的是能够同时获取多个. 下面看一个例子:

#include <cassert>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>

static int g_inc_index = 0;
static int g_dec_index = 0;
std::mutex g_inc_mutex;
std::mutex g_dec_mutex;

static void _run(const int count) {
    for (int i = 0; i < count; i++) {
        std::scoped_lock lock(g_inc_mutex, g_dec_mutex);
        ++g_inc_index;
        --g_dec_index;
    }
}

int main(void) {
    std::vector<std::thread> v_th;
    const int count = 1000;

    for (int i = 0; i < 10; i++) {
        v_th.emplace_back(_run, count);
    }

    for (auto &t : v_th) {
        t.join();
    }

    assert(g_inc_index == -g_dec_index);
    return 0;
}

如果觉得有帮助,可以扫描右边的微信打赏码支持一下.

参考:

Leave a Reply

Your email address will not be published. Required fields are marked *