c++多线程基础三 --同步并发
1 条件变量
1.1 condition_variable
std::condition_variable实际上是一个类,是一个和条件相关的类;
-
condition_variable成员函数:
![condition_variable成员函数]()
结合std::unique_lock<std::mutex> 使用 -
使用规则:
![使用规则]()
-
wait 使用
void wait( std::unique_lock<std::mutex>& lock ); (1) -------------------------------------------------------- template< class Predicate > (2) void wait( std::unique_lock<std::mutex>& lock, Predicate pred );- (1) 调用:相当于 (2)的第二个参数为false,wait()将解锁互斥量,并阻塞到本行;
- (2) 调用:第二个参数为true,wait()直接返回并继续执行。
-
notify_one唤醒线程
- wait()不断尝试获取互斥量锁,如果获取不到那么流程就卡在wait()这里等待获取,如果获取到了,那么wait()就继续执行,获取到了锁
- 如果wait有第二个参数就判断这个lambda表达式。
a): 如果表达式为false,那wait又对互斥量解锁,然后又休眠,等待再次被notify_one()唤醒
b): 如果lambda表达式为true,则wait返回,流程可以继续执行(此时互斥量已被锁住)。 - 如果wait没有第二个参数,则wait返回,流程走下去。
注意:wait和wait_for 会先判断这个lambda表达式,如果表达式返回结果为true,则直接唤醒,流程继续执行,不会wait线程。
-
条件变量注意事项
-
条件变量虚假唤醒
whlie (tasks.empty()) { pthread_cond_wait(&mycv, &mymutex); }为什么不写成这样?
if (tasks.empty()) { pthread_cond_wait(&mycv, &mymutex); }因为操作系统唤醒
pthread_cond_wait时,tasks.empty()可能仍为true,即操作系统可能再某些情况下唤醒条件变量,也就是说存在没有其他线程向条件变量发送信号,但等待此条件变量的线程有可能醒来的情形。使用lambda表达式来解决,不用while循环,
cv.wait(lck, [] {return !tasks.empty();}); -
条件变量信号丢失
如果一个条件变量信号在产生时(调用pthread_cond_signal或者pthread_cond_broadcast) ,没有相关线程调用pthread_cond_wait捕获该信号,该信号就会永久丢失,再次调用pthread_cond_wait会导致永久阻塞。要注意这种情况,建议使用sem 信号
-


浙公网安备 33010602011771号