Li.*_*Cao 2 c++ deadlock condition-variable
我正在学习condition_variable并运行一些例子.我很好奇,如果我对块进行注释,为什么以下代码会出现死锁.这是使用condition_variable的简单消费者和生产者示例.我认为这是一个僵局问题,不是吗?
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
mutex mtx;
condition_variable cv;
int cargo = 0;
bool shipment_available()
{
return cargo != 0;
}
void consume(int cnt)
{
for (int i = 0; i < cnt; i++)
{
unique_lock<mutex> lck(mtx);
cv.wait(lck, shipment_available);
printf("%d\n", cargo);
cargo = 0;
}
}
int main()
{
thread consumer_thread(consume, 10);
for (int i = 0; i < 10; i++)
{
//while (shipment_available()) // Dead lock without this block
//{
// std::this_thread::yield();
//}
unique_lock<mutex> lck(mtx);
cargo = i + 1;
cv.notify_one();
}
consumer_thread.join();
}
Run Code Online (Sandbox Code Playgroud)
如果我取消注释块,它运行良好.
因此,走过这种极有可能的可能性:
main()
启动消费者线程.main()
锁之前,锁定它,递增cargo
并触发通知,然后通过scope-rotation释放互斥锁十次.main()
现在运行到join
消费者线程.cargo
确实为零,所以它等待条件变量(在过程中释放互斥锁)以获得永远不会出现的信号.唯一发送过该信号的是main()
,它只是等待消费者线程加入,这现在永远不会发生.简而言之,您似乎相信条件变量信号会叠加.事实并非如此.如果在发布通知时没有人正在等待通知,那么它就会丢失给以太.
最后,这很重要,你的"修复"本身就是完全错误的.该shipment_available
函数检查谓词数据(即必须由互斥体保护的数据,不仅用于修改,而且用于检查).检查没有锁定互斥锁的main
是竞争条件的配方.
我的建议是将货物减少一个而不是将货物归零.或者,您可以在将其归零之前增加i
值cargo
,从而加速i
上升到cnt
极限,但您似乎使用上升货物量,因此您必须相应地进行其他调整.
归档时间: |
|
查看次数: |
79 次 |
最近记录: |