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);
}