请看以下代码:
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();
}
是否会发生以下场景?
terminate_worker()
的主线程;terminate
设置为 true
,然后向工作线程发出信号。 terminate
加载。这一步还没有看到主线程对terminate
的改变,所以工作线程决定等待另一个信号。 我想知道这是可能的。据我了解,
std::atomic
只保证没有竞争条件,但内存顺序是另一回事。问题:terminate
不是原子变量而只是 bool
,这可能吗?还是原子性与此无关? 谢谢你。
最佳答案
我不相信,你所描述的是可能的,因为 cv.notify_all()
afaik(如果我错了,请纠正我)与 wait()
同步,所以当工作线程醒来时,它会看到 terminate
的变化。
但是:
死锁可以通过以下方式发生:
terminate
标志仍然为 false。 terminate
标志并调用 cv.notify_all()
。 join
并阻止。 cv.wait()
)并阻塞。 解决方案:
虽然您在调用 cv.notify 时不必持有锁,但您
terminate
(即使它是原子代码) 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();
}
关于c++ - 在这个简单的场景中是否可能出现死锁?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41340960/