C++多线程编程之condition_variable

  • Post author:
  • Post category:其他


参考

www.cplusplus.com



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

由当前线程上锁,并被该函数获得。



版权声明:本文为llb_1203原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。