文章目录
std::condition_variable
条件变量可以阻塞调用线程,直至有通知到来(
notified
)。
当条件变量的某个
wait
函数被调用时,该函数将使用一个管理
mutex
对象的
unique_lock
来锁住当前线程。当前线程将被阻塞,直至使用了同一个条件变量的另外一个线程调用了
notification
函数中的一个。
condition_variable
总是使用
unique_lock<mutex>
,而
condition_variable_any
可以和任意的锁类型配合使用。
构造函数
condition_variable();
condition_variable (const condition_variable&) = delete;
构造一个
condition_variable
对象,不支持拷贝和移动操作。
析构函数
~condition_variable();
销毁
condition_variable
对象。任何被阻塞在这个条件变量上的线程都应该在调用析构函数之前被
notified
;而调用析构函数之后,任何线程都不应该再调用
wait
函数。
condition_variable::notify_all
void notify_all() noexcept;
唤醒当前所有因等待该条件变量而阻塞的线程;若没有线程等待,则什么也不做。
condition_variable::notify_one
void notify_one() noexcept;
功能与
notify_all
相同,区别在于如果有多个等待线程,则随机选择其中一个线程唤醒。
condition_variable::wait
void wait (unique_lock<mutex>& lck);
template <class Predicate>
void wait (unique_lock<mutex>& lck, Predicate pred);
当前线程应该对
lck
管理的
mutex
上锁,并且被阻塞直至收到通知(notified)。
阻塞当前线程的同时,该函数会自动调用
lck.unlock()
函数,并允许其他被阻塞线程继续运行。
一旦被其他线程通知,该函数将解除阻塞并调用
lck.lock()
,恢复
lck
状态至刚调用该函数时的状态,然后函数将返回。需要注意的是,在返回之前,最后一次对
mutex
上锁可能会再次阻塞当前线程。
通常,其他线程调用
notify_one
或
notify_all
会唤醒该函数,但有时这两个函数都没被调用也会产生一个通知,即虚假唤醒。因此,
wait
函数的使用者需确保
重新开始的条件都得到满足。
如果谓词
pred
被指定,在该函数只有在
pred
返回
false
时才会阻塞当前线程,并且收到通知后只有在
pred
返回
true
时才能解除阻塞。第二种用法可以用于防止虚假唤醒,其执行过程如下:
while(!pred())
wait(lck);
pred
是没有形参的可调用对象或函数,并返回可转换为
bool
类型的值。该
pred
会被重复调用直至返回值为
true
。
condition_variable::wait_for
//无条件版本
template <class Rep, class Period>
cv_status wait_for (unique_lock<mutex>& lck,
const chrono::duration<Rep,Period>& rel_time);
//有条件版本
template <class Rep, class Period, class Predicate>
bool wait_for (unique_lock<mutex>& lck,
const chrono::duration<Rep,Period>& rel_time, Predicate pred);
功能与
wait
相同,区别在于可以指定一个
rel_time
相对时间,若等待时间超过该时间或在该时间内收到通知,则线程会被解除阻塞。
对于无条件版本,其返回值是枚举类型
cv_status
。若因超过指定时间而返回,则返回值为枚举量
timeout
;对于其他情况,返回值为
no_timeout
。
对于有条件版本,其返回值由谓词
pred
决定,与
pred()
返回值一致。
condition_variable::wait_until
//无条件版本
template <class Clock, class Duration>
cv_status wait_until (unique_lock<mutex>& lck,
const chrono::time_point<Clock,Duration>& abs_time);
//有条件版本
template <class Clock, class Duration, class Predicate>
bool wait_until (unique_lock<mutex>& lck,
const chrono::time_point<Clock,Duration>& abs_time,
Predicate pred);
功能与
wait
相同,区别在于可以指定一个
abs_time
绝对时间,若当前时间达到该绝对时间或在此期间内收到通知信号,则当前线程被解除阻塞。
该函数返回值与
wait_for
相同。
std::class cv_status
enum class cv_status {no_timeout, timeout};
该类型指示函数是否因超时而返回。
std::notify_all_at_thread_exit
void notify_all_at_thread_exit (condition_variable& cond, unique_lock<mutex> lck);
当调用该函数的线程退出时,会通知所有等待
cond
的线程重新运行。
该函数也会获得由
lck
管理的
mutex
对象的所有权,该
mutex
对象被存储在函数内部,并在线程退出时解锁(在通知所有线程之前操作)。
形参
lck
由当前线程上锁,并被该函数获得。