1.std::mutex类
1.构造函数,std::mutex不允许拷贝构造,也不允许 move 拷贝,最初产生的 mutex 对象是处于 unlocked 状态的。
2.lock(),调用线程将锁住该互斥量。线程调用该函数会发生下面 3 种情况:①如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用 unlock之前,该线程一直拥有该锁。②如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住。③如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。
3.unlock(), 解锁,释放对互斥量的所有权
4.unlock 和lock配套使用
5.必须在每个离开函数的路径上调用unlock。
2.std::lock_guard类
std::lock_guard使用起来比较简单,除了构造函数外没有其他成员函数。
优势在于不用配对使用
#include <thread> #include <iostream> #include <mutex> std::mutex some_mutex; void add() { std::lock_guard<std::mutex> guard(some_mutex); }
3.使用std::unique_lock灵活锁定
为了实现锁粒度,std::lock_guard就显得不够灵活,一个例子:
#include <thread> #include <iostream> #include <mutex> std::mutex some_mutex; void add() { { //这边的括号是为了作用域,以便自动解锁 std::lock_guard<std::mutex> guard(some_mutex); //do something_1 } //do something_2 { std::lock_guard<std::mutex> guard(some_mutex); //do something_3 } }
使用unique_lock
void add() { std::unique_lock<std::mutex> lock_1(some_mutex,std::defer_lock);//保留互斥元为未锁定 std::lock(lock_1); //互斥元在这里锁定 // do something_1 std::unlock(lock_1); //do something_2 std::lock(lock_1); // do something_3 std::unlock(lock_1); }
4.使用相同的顺序锁定互斥元来避免死锁
使用std::lock函数
std::mutex m1,m2; void mutexer() { std::lock(m1, m2); //锁定这两个互斥元 //构建两个实例,告知该互斥元对象已被锁定,只是获取所有权,并不试图锁定互斥元 std::lock_guard<std::mutex> lock_1(m1, std::adopt_lock); std::lock_guard<std::mutex> lock_2(m2, std::adopt_lock); }