C++多线程编程条件变量虚假唤醒(spurious wakeup)

来源:互联网 发布:软件大数据咨询顾问 编辑:程序博客网 时间:2024/05/17 18:13

最近在使用C++多线程的进行生产者消费者编程过程中遇到多线程同步的问题,比较奇怪的是条件变量等待过程中在条件未满足的线程竟然被唤醒了。

原始代码:

std::unique_lock<std::mutex> lk(mutex)if(queue.empty()){    cond_var_.wait(lk)    queue.front();    ...}
这种代码书写方式会存在以下情况:

有三个线程在等待一个队列,有以下情况发生:
(1)线程1在取到queue元素之后去做处理,之后queue为空
(2)线程2判断queue是否为空,此时queue为空,此时线程2阻塞在wait上
(3)线程3开始向queue里添加一个元素,然后调用notify
(4)此时阻塞在wait上的线程2被唤醒获取queue lock之前,如果这个时候线程1恰好处理完毕然后获取锁重新取queue里的元素
(5)如果在线程2唤醒并获取queue lock之后,在其取走queue里的元素之前线程1已经将元素取走,这个时候线程2就出现了假象唤醒

上述过程就是一个spurious wakeup过程。

那么将代码稍作修改:

std::unique_lock<std::mutex> lk(mutex)while(queue.empty()){    cond_var_.wait(lk);    ...}queue.front()
用一个循环来查询queue是否可以,即使在条件变量被spurious wakeup的时候获取queue lock之后还是需要去check queue是否为空,这样避免了假象唤醒。

阅读全文
0 0
原创粉丝点击