c++11 mutex/atomic

谁说我不能喝 提交于 2021-01-13 05:34:14

mutex/atomic

c++ basic data struct is not thread-safe, only multithreading read and no write is safe. mutex/atomic tool can solve data race, but if you use them incorrect, it will cause deadlock.

mutex

basic mutex

basic mutex is std::mutex object, very simple rule: call member function lock to lock it, call unlock to unlock it. but you can not lock it when it locked, also not unlock it when it not locked, or it will cause deadlock.

std::mutex mtx;
mtx.lock();
// ...
mtx.unlock();

recursive mutex

recursive mutex is std::recursive_mutex object, difference from basic mutex, it will not cause deadlock when you locked it twice or more, but you need to unlock it the same times as you locked it, it is slower than basic mutex.

std::recursive_mutex rmtx;
rmtx.lock();
// ...
rmtx.unlock();

guard lock

guard lock is std::guard_lock<T> template, use feature RAII to lock/unlock mutex when object constructs and destructs. you just need a mutex object for its construct, you can not call lock/unlock for its mutex object manually.

std::mutex mtx;
std::guard_lock<std::mutex> lg(mtx);
// ...

unique lock

unique lock is std::unique_lock<T> template, very similar with guard lock, but you can call lock/unlock for its mutex object manually, so it is always used with condition variable, it is slow than guard lock.

std::mutex mtx;
std::unique_lock<std::mutex> lg(mtx);
// ...
mtx.unlock()
// ...
mtx.lock();

atomic

once atomic

sometimes you need a code part just run once, but many threads want to do that. you can use std::once_flag variable and std::call_once function to avoid data race.

std::once_flag of;
void once_func()
{
    // init...
}
// ...
std::call_once(of, once_func);

regular atomic

atomic is std::atomic<T> template, T must be c++ basic type, such as int, double and so on, use this template, this variable will be atomic, most of its operation is the same to its basic type but slow a little bit.

std::atomic<int> cnt;
// ...
++cnt;

memory order

atomic has six memory order, default use std::memory_order_seq_cst, unless very need perfermance, do not use other memory orders, its very easy to cause problem, here gives a spin lock class implements.

class spin_lock {
public:
    spin_lock() {
        while (flag.test_and_set(std::memory_order_acquire)) {}
    }
    ~spin_lock() {
        flag.clear(std::memory_order_release);
    }
private:
    std::atomic_flag flag;
};
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!