条件变量condition_variable
条件变量类是一个同步原语,它可以在同一时间阻塞一个线程或者多个线程,直到其他线程改变了共享变量(条件)并通知。它必须跟互斥锁一起配合使用,条件变量之所以要和互斥锁一起使用,主要是因为互斥锁的一个明显的特点就是它只有两种状态:锁定和非锁定,而条件变量可以通过允许线程阻塞和等待另一个线程发送信号来弥补互斥锁的不足,所以互斥锁和条件变量通常一起使用。条件变量本身不是锁,但它也可以造成线程阻塞,通常与互斥锁配合使用,给多线程提供一个会合的场所。
头文件
cpp
#include <condition_variable>
class condition_variable;
构造函数
cpp
condition_variable();
condition_variable(const condition_variable &) = delete;
条件变量的等待
cpp
template <class Predicate>
void wait(std::unique_lock<std::mutex> &lock, Predicate pred);
void wait(std::unique_lock<std::mutex> &lock);
如果第二个参数lambda表达式返回值是true,那wait()直接返回;如果第二个参数lambda表达式返回值是false,那wait()将解锁互斥量,并堵塞到本行,那堵塞到什么时候为止呢?堵塞到其他线程调用notify_one()或者notify_all()成员函数为止。
如果wait()函数没有第二个参数,那么就跟第二个参数lambda表达式返回false效果一样,wait()将解锁互斥量,并堵塞到本行,堵塞到其他线程调用notify_one()或者notify_all()成员函数为止。当其它线程用notify_one()或者notify_all()将本wait(原来是睡着/堵塞)的状态唤醒后,wait()就开始恢复干活了,恢复wait干什么活呢?
- wait()不断的尝试重新获取互斥量锁,如果获取不到,那么流程就卡在wait这里等着获取,如果获取到了,那么wait()就继续执行下面一步。
- 如果wait有第二个参数(lambda),就判断这个lambda表达式,如果lambda表达式为false,那wait又对互斥量解锁,然后又休眠这里等待再次被notify_one()或者notify_all()唤醒;如果lambda表达式为true,则wait返回,流程走下去(此时互斥锁被锁着);如果wait没有第二个参数,则wait直接返回,流程走下来。
cpp
template <class Rep, class Period>
std::cv_status wait_for(std::unique_lock<std::mutex> &lock, const std::chrono::duration<Rep, Period> &rel_time);
template <class Rep, class Period, class Predicate>
bool wait_for(std::unique_lock<std::mutex> &lock, const std::chrono::duration<Rep, Period> &rel_time, Predicate pred);
template <class Clock, class Duration>
std::cv_status wait_until(std::unique_lock<std::mutex> &lock, const std::chrono::time_point<Clock, Duration> &timeout_time);
template <class Clock, class Duration, class Pred>
bool wait_until(std::unique_lock<std::mutex> &lock, timeout_time, const std::chrono::time_point<Clock, Duration> &Pred pred);
条件变量的通知
cpp
// 通知一个等待线程
void notify_one() noexcept;
// 通知所有等待线程
void notify_all() noexcept;