condition_variable
类是用来阻塞线程或者是多线程的同步原语,直到另一个线程修改完共享变量(the condition),并通知
condition_variable
。
尝试修改变量的线程必须:
- 获得std::mutex,典型的通过std::lock_guard()
- 加锁后对变量进行修改
- 在std::condition_variable上执行 notify_one or notify_all
即使共享变量是原子性的,为了正确的把修改传递给等待线程,共享变量在互斥量下也必须被修改。
任何在std::condition_variable下尝试等待的线程必须:
- 获得std::unique_lock<std::mutex>,该mutex通常用来保护共享变量
- 执行 wait, wait_for, or wait_until。该等待操作原子性的释放互斥量并阻塞线程执行。
- 当条件变量被通知,或者是超时,或者是虚假唤醒发生,该线程被唤醒,互斥量被原子性的获得。线程应该检查一下条件,如果是虚假唤醒的话应该继续等待;
std::condition_variable只能和std::unique_lock<std::mutex>一起使用,在某些平台上能够使资源最大限度的利用。
一些函数:
让我们来看一下wait的两种函数形式:
- notify_one 通知一个等待线程
- notify_all 通知所有等待线程
- wait 阻塞当前线程直到条件变量被唤醒
- wait_for 阻塞当前线程直到条件变量被唤醒或者是过了特定的时间间隔
- wait_until 阻塞当前线程直到条件变量被唤醒,或者是达到了特定的时间点
我们首先看一下wait()函数的两种形式:
void wait( std::unique_lock<std::mutex>& lock );
template< class Predicate >
void wait( std::unique_lock<std::mutex>& lock, Predicate pred );
wait()函数的主要功能,阻塞当前线程,将线程挂起,直到条件变量被通知或者是虚假唤醒出现。
1)调用wait()函数之后,原子性地释放锁(解锁),阻塞正在执行的线程,并把线程加入等待的线程列表(线程挂起),当调用 notify_all() or notify_one()的时候线程变为不阻塞状态(通过虚假唤醒也可),当线程不阻塞的时候,无论是什么原因,lock都被重新获得(加锁),wait()函数退出,如果函数是