1、mutex
- 不安全,因为代码之间可能由于逻辑走掉了,代码发生异常了,造成锁没有释放掉,成死锁
2、lock_guard
- 利用的是智能指针的概念。
- 在它的构造函数里面可以主动的获取这把锁lock。
- 当这个对象出作用域,自动调用析构函数,析构函数中有释放锁的操作unlock。
- 它把左值引用的拷贝构造函数和赋值函数都删除掉了。
不可能用在函数参数传递或者返回过程中,因为要用到拷贝构造函数和赋值函数,只能用在简单的加锁解锁临界区代码段的互斥操作中。
只能用在简单的加锁解锁的临界区代码中;
3、unique_lock
利用的是智能指针的概念。
在它的构造函数里面可以主动的获取这把锁lock。
当这个对象出作用域,自动调用析构函数,析构函数中有释放锁的操作unlock。
它把左值引用的拷贝构造函数和赋值函数都删除掉了。
但是它提供了右值引用的拷贝构造函数和赋值函数。
所以可以用在函数参数传递或者返回过程中。
它还提供了一对lock和unlock方法。
std::mutex mtx;//底层是pthread_mutex_t
std::condition_variable cv;//底层是pthread_condition_t
unique_lock<std::mutex> lck(mtx);
cv.wait(lck);
//=> #1.使当前线程进入等待状态 #2.lck.unlock可以把mtx给释放掉
注意: 条件变量cv.wait里面传的是unique_lock,也只能传unique_lock,因为lock_gard将拷贝构造和赋值重载都delete了(实参到形参是一个拷贝构造的过程,传不进来)
4、lock_gard和unique_lock对比
- lock_gard和unique_lock可以看成unique_ptr和scope_ptr之间的关系;
- lock_gard和unique_lock做的事情是一样的,都是在构造函数中国自动执行mutex的lock()函数,在析构函数中自动执行mutex的unlock()函数。
lock_gard源码:
unique_lock源码:
5、notify_all
/*
通知在cv上等待的线程,条件成立了,起来干活了!
其它在cv上等待的线程,收到通知,
从等待状态 =》到阻塞状态(不能直接运行)
=》只有当前线程释放锁了,其他线程才能获取互斥锁了 =》线程继续往下执行
*/
cv.notify_all();