C++ 在这个简单的场景中是否可能出现死锁?
请参阅以下代码:C++ 在这个简单的场景中是否可能出现死锁?,c++,multithreading,memory-barriers,C++,Multithreading,Memory Barriers,请参阅以下代码: std::mutex mutex; std::condition_variable cv; std::atomic<bool> terminate; // Worker thread routine void work() { while( !terminate ) { { std::unique_lock<std::mutex> lg{ mutex }; cv.wait(lg);
std::mutex mutex;
std::condition_variable cv;
std::atomic<bool> terminate;
// Worker thread routine
void work() {
while( !terminate ) {
{
std::unique_lock<std::mutex> lg{ mutex };
cv.wait(lg);
// Do something
}
// Do something
}
}
// This function is called from the main thread
void terminate_worker() {
terminate = true;
cv.notify_all();
worker_thread.join();
}
std::mutex mutex;
std::条件变量cv;
std::原子终止;
//工作线程例程
无效工作(){
而(!终止){
{
std::unique_lock lg{mutex};
cv.wait(lg);
//做点什么
}
//做点什么
}
}
//此函数是从主线程调用的
无效终止工作人员(){
终止=真;
cv.通知所有人();
worker_thread.join();
}
是否会发生以下情况
terminate_worker()
;
- 主线程将原子变量
设置为terminate
,然后向工作线程发送信号true
- 工作线程现在唤醒,执行其工作并从
终止加载。在这一步中,还看不到主线程对
所做的更改,因此工作线程决定等待另一个信号terminate
std::atomic
只保证没有竞争条件,但内存顺序是另一回事。问题:
terminate
不是一个原子变量,而只是bool
,这是可能的吗?或者原子性与此无关谢谢。我不相信,你所描述的是可能的,因为
cv.notify_all()
afaik(如果我错了,请纠正我)与wait()
同步,所以当工作线程醒来时,它将看到对终止的更改
但是:
死锁可以通过以下方式发生:
工作线程(WT)确定终止
标志仍然为false
主线程(MT)设置terminate
标志并调用cv.notify\u all()
因为现在没有人在等待条件变量,所以通知会“丢失/忽略”
MT调用连接
和块
WT进入睡眠状态(cv.wait()
)并阻塞李>
解决方案:
当你打电话给cv.notify时,你不必持有锁,但是
- 在修改
终止时必须持有锁(即使是原子锁)
- 必须确保在您持有相同的锁时,对条件进行检查并实际调用
wait
李>
这就是为什么有一种形式的wait
,它在发送线程进入睡眠之前执行此检查
更正后的代码(更改最少)可能如下所示:
// Worker thread routine
void work() {
while( !terminate ) {
{
std::unique_lock<std::mutex> lg{ mutex };
if (!terminate) {
cv.wait(lg);
}
// Do something
}
// Do something
}
}
// This function is called from the main thread
void terminate_worker() {
{
std::lock_guard<std::mutex> lg(mutex);
terminate = true;
}
cv.notify_all();
worker_thread.join();
}
//辅助线程例程
无效工作(){
而(!终止){
{
std::unique_lock lg{mutex};
如果(!终止){
cv.wait(lg);
}
//做点什么
}
//做点什么
}
}
//此函数是从主线程调用的
无效终止工作人员(){
{
标准:锁紧保护lg(互斥);
终止=真;
}
cv.通知所有人();
worker_thread.join();
}
@melak47请提供更多详细信息。我知道这是关于std::memory\u order
。但是我不知道std::condition_variable
如何与内存顺序限制一起工作。相关:@n.m.这已经完成了。OP询问原子存储(使用memororder\u seq\u cst
)和condition\u变量::notify\u all
)之间的排序/同步。当terminate
不是原子时,此代码按预期工作。使其原子化是冗余和浪费的。在任何情况下,OP都应该在等待后检查terminate变量的状态。在提供的代码中,我们无法区分通知条件变量的原因。它可以是terminete请求,也可以是与另一个线程的正常同步。@paweldac:是的,他可能应该(在不知道业务逻辑的情况下,很难说),但这与是否会发生死锁的问题有什么关系?非常感谢。我发现在链接中[它被描述为“即使共享变量是原子的,也必须在互斥下修改它,以便正确地将修改发布到等待的线程。”这是关于你刚才描述的吗?还是一个不同的故事?还有,使终止原子化是否毫无意义?也就是说,我可以使用bool
,不是吗?