1、条件变量
与互斥锁组合使用的东西,条件变量
使用
包含头文件#include<condition_variable>
与C内的条件变量不同点
condition_variable初始化不用单独调用函数实现,在构造里实现
回收同理,在析构里实现
需要掌握的函数
wait等——wait_for wait_util可以防止条件,以及时间,避免死锁
notify通知——notify_one notify_all
用途
可以结合互斥锁,实现线程同步,完成一些如生产者、消费者模型这样的功能
生产者消费者模型
1.涉及到的概念:有若干生产者,若干消费者,同步队列(阻塞队列,环形队列),还有管理者
2.生产者向队列中生产产品,消费者监听队列,一旦有产品,就从队列中拉取数据
3.2个阻塞:一旦队列满了,生产者阻塞,一旦队列为空,消费者阻塞
通知
很简单,是在需要通信的时候,发送通知
通知一个,是唤醒一个正在wait的,通知所有,是唤醒所有wait的
如果没有wait的条件变量,就会丢失
wait等待
有两种函数
wait(参数1)
参数是一个已经上锁的unique_lock(已上锁的互斥锁),执行wait会释放锁,然后阻塞当前线程,直到收到通知
收到通知,获取锁,解除阻塞(获取到了,解除阻塞的顺序是无法保证的),然后执行后续代码
wait(参数1,参数2)
多了一个参数2
是一个可调用对象,调用返回真假true|false
如果当前已经wait了,收到通知会调用可调用对象
调用结果为真可以解除,通知就生效,如果调用结果为假,通知就没作用,防止虚假唤醒
类似原来的while(){wait();}
虚假唤醒
没有通知,wait返回
虚假唤醒发生条件
是操作系统的问题
1.可能由于系统线程调度导致
2.可能是系统中断,如果一旦发生中断,系统会唤醒一些线程去处理中断
template<typename _Lock, typename _Predicate>
void
wait(_Lock& __lock, _Predicate __p)
{
while (!__p())
wait(__lock);
}
如果调用对象执行后为真,才执行wait,就会跳过wait
如果调用对象执行后为假,才执行wait,就会阻塞,然后等待通知
通知等到了,如果调用对象执行后为假,就继续等待,通知无效
如果调用对象执行后为真,就往下执行
对于返回值需要变化,可以通过标志位来完成变化
2、代码
1、点击按钮发送信号
2、输出标志位
输出结果
3、执行条件变量阻塞
4、创建线程