mutex和condition_variable
mutex
- mutex是用于保护共享数据的,避免多线程同时访问
- 头文件:
#include <mutex>
- 创建
mutex
:
mutex m_lock;
- 加锁:
lock
、try_lock
(1)lock
加锁操作,若互斥量已加锁则阻塞等待
(2)try_lock
,表示尝试加锁,若加锁成功返回true,否则返回false,不会阻塞
mutex m_lock;
m_lock.lock();
m_lock.try_lock(); //返回false
- 解锁:
unlock
mutex m_lock;
m_lock.try_lock(); //返回true
m_lock.unlock(); //解锁
lock_guard
:
(1)lock_guarad
类似于使用智能指针管理堆内存,lock_guard
简化了lock
和unlock
的操作,在创建lock_guard时,其构造函数会自动对互斥量加锁,当lock_guard被销毁时,其析构函数会自动将互斥量解锁
mutex m_lock;
{
lock_guard<mutex> locker(m_lock); //自动执行lock();
} //离开作用域时自动解锁
unique_lock
:
(1)unique_lock
的用法类似于unique_ptr
,用户管理互斥量,与lock_guard
功能类似,在初始化阶段,就对管理的互斥量进行加锁,并在其析构函数中对管理的互斥量进行解锁
void func()
{
unique_lock <mutex> locker(m_lock)
ready = true; //修改全局变量
} //所有语句执行完后,再进行互斥量的解锁
condition_variable
- 条件变量
condition_variable
是C++11提供的一种用于等待的同步机制,可以阻塞一个或多个线程,直到收到另一个线程的通知,才会唤醒当前阻塞的线程 - 条件变量一般与互斥量配合使用
- 条件变量的头文件
#include <condition_variable>
- 条件变量的声明:
condition_variable cv; //定义了1个条件变量
wait
:
(1)wait
的原型:void waita(unique_lock<mutex> & )
,所以它是在等待管理互斥量(mutex)的unique_lock对象
(2)只要调用wait
就会阻塞等待,直到有其他线程的通知
(3)当调用wait
阻塞后,该函数会对locker管理的互斥量进行解锁,使得其他被阻塞在锁竞争上的线程继续进行
(4)一旦获得其他线程的通知,取消阻塞,wait函数会自动对locker管理的互斥量进行加锁,使得m_lock的状态与调用wait之前相同
mutex m_lock;
condition_variable cv;
bool ready = false;
unique_lock<mutex> locker(m_lock); //创建unique_lock时会自动对m_lock加锁
while(!ready)
cv.wait(locker);
(5)wait还有一个原型,可以接受一个返回bool类型的第二参数
- 只有当 ready条件为false时调用 wait() 才会阻塞当前线程
- 收到其他线程的通知后只有当 ready为true 时才会被解除阻塞
mutex m_lock;
condition_variable cv;
bool ready = false;
bool get_ready(){return ready;}
unique_lock<mutex> locker(m_lock); //创建unique_lock时会自动对m_lock加锁
cv.wait(locker, get_ready); //也是可以的
notify_all
:
(1)唤醒所有等待线程,若没有线程等待,则什么也不做
mutex m_lock;
condition_variable cv;
void go()
{
unique_lock<mutex> locker(m_lock);
cv.notify_all(); //唤醒所有等待线程
}