条件变量死锁
Condition variable deadlock
我的代码中有一个死锁问题,与使用条件变量有关。这更像是一个设计问题,而不是纯粹的代码问题。一旦我理解了正确的设计,我写代码就没有问题了。我有以下场景:
- 线程A等待一个条件变量。
- 线程B调用notify_all,线程A苏醒。
这当然是我想要发生的事情,也是当一切都按照预期工作时发生的事情。但有时,我会得到以下场景:
- 线程A在等待条件变量之前执行代码。
- 线程B调用notify_all,认为线程A正在等待。 线程A开始等待条件变量,没有意识到线程B已经告诉它停止等待。僵局。
解决这个问题的最好方法是什么?我想不出一种可靠的方法来检查线程a是否实际上正在等待,以便知道何时应该在线程b中调用notify_all。我必须求助于time_lock吗?我不愿意。
在线程A等待条件变量之前,它必须持有一个互斥锁。最简单的解决方案是确保线程B在调用notify_all时持有相同的互斥锁。像这样:
std::mutex m;
std::condition_variable cv;
int the_condition = 0;
Thread A: {
std::unique_lock<std::mutex> lock(m);
do something
while (the_condition == 0) {
cv.wait(lock);
}
now the_condition != 0 and thread A has the mutex
do something else
} // releases the mutex;
Thread B: {
std::unique_lock<std::mutex> lock(m);
do something that makes the_condition != 0
cv.notify_all();
} // releases the mutex
这保证了线程B只在线程A获取互斥锁之前或线程A等待条件变量时执行notify_all()。
这里的另一个关键是等待the_condition为真的while循环。一旦A线程有了互斥锁,其他线程就不可能改变这个条件,除非A线程测试了这个条件,发现它为假,并开始等待(从而释放互斥锁)。
关键是:您真正等待的是the_condition的值变为非零,std::condition_variable::notify_all只是告诉您线程B认为线程A应该唤醒并重新测试。
条件变量必须始终与互斥锁相关联,以避免一个线程准备等待而另一个线程可能在第一个线程实际等待之前发出条件信号而导致死锁。线程将永远等待一个永远不会发送的信号。任何互斥锁都可以使用,互斥锁和条件变量之间没有明确的联系。
相关文章:
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何在没有死锁和/或争用的情况下正确使用 std::mutex C++?
- 用C++中的std::condition_variable将线程置于死锁中会有风险吗
- 使用 std::async 时死锁,将来作为成员
- 如何调试读写器锁的死锁?
- 为什么在Visual Studio 2013上的std::this_thread::sleep_for上死锁
- localtime() 函数正在调用 ___lll_lock_wait_private(),这会使线程陷入死锁
- 如何重现 Boost 进程文档提示的死锁?
- 多线程Windows GUI应用程序中的死锁
- 为什么printf会导致与future.get的死锁,而cout则不会?
- 互锁变量访问(在布尔值上)和 std::atomic_flag 之间的区别
- C++中具有阻塞队列和障碍的死锁
- 死锁使用 std::mutex 来保护多个线程中的 cout
- 避免并发等待对象中的死锁
- 在VC++中从DLLMAIN内部调用D3D的CREATEDEVICE时,它会创建一个死锁(loaderlock?)。有没有办法克服这个问题?最终目标内
- 当用2个螺纹锁定时,将recursive_mutex死锁
- 程序在 C++11 中使用条件变量进入死锁
- 一个线程提升的死锁
- 两个条件变量和避免死锁
- 条件变量死锁