两个std :: unique_lock在同一静音上使用会导致死锁
Two std::unique_lock used on same mutex causes deadlock ?
我在代码评论stack Exchange上找到了实现生产者消费者问题的代码。我在此处发布一部分代码。
在给定代码中,让我们考虑一个场景,当生产者通过调用void add(int num)
产生值时,它在Mutex mu
和buffer.size()==size_
上获取锁定,这使得生产者由于条件可变cond
。
同时,发生了上下文开关,消费者调用功能int remove()
要消耗值,它试图在Mutex mu
上获取锁,但是锁已被生产者先前获取,因此失败了,从不消耗。价值,因此导致僵局。
我在哪里出错?因为该代码在我运行时似乎可以正常工作,所以调试它对我没有帮助。
谢谢
void add(int num) {
while (true) {
std::unique_lock<std::mutex> locker(mu);
cond.wait(locker, [this](){return buffer_.size() < size_;});
buffer_.push_back(num);
locker.unlock();
cond.notify_all();
return;
}
}
int remove() {
while (true)
{
std::unique_lock<std::mutex> locker(mu);
cond.wait(locker, [this](){return buffer_.size() > 0;});
int back = buffer_.back();
buffer_.pop_back();
locker.unlock();
cond.notify_all();
return back;
}
}
std::condition_variable::wait(lock, predicate)
的想法是,您要等到谓词达到谓词,然后在Mutex上锁定。要在原子上进行此操作(大多数情况下这很重要),您必须先锁定互斥X,然后等待将其释放并锁定它以检查谓词。如果满足,则静音锁定锁定,执行继续。如果不是,则互斥X将再次发布。
淘汰的答案很好,但是对什么是"原子"的详细信息很有用。
条件变量上的wait
操作具有前提条件和后结构,即呼叫者锁定了静音者中传递的情况。wait
操作在内部解锁互斥X,并以保证不会错过任何notify
或notify_all
操作的方式从其他线程中丢失任何因解锁互斥X而发生的线程。在wait
内部,静音的解锁并输入等待通知的状态相对于彼此而言是原子。这避免了睡眠/唤醒比赛。
条件临界部分形式在内部测试谓词。但是,这仍然取决于正确完成的通知。
从某种意义上说,可以将wait
视为这样做:
while (!predicate()) {
mutex.unlock();
/* sleep for a short time or spin */
mutex.lock();
}
带有通知的条件变量允许中间的评论线有效。给出:
while (!predicate()) {
atomic { /* This is the key part. */
mutex.unlock();
sleep_until_notified();
}
mutex.lock();
}
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何在没有死锁和/或争用的情况下正确使用 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则不会?
- C++中具有阻塞队列和障碍的死锁
- 死锁使用 std::mutex 来保护多个线程中的 cout
- 避免并发等待对象中的死锁
- 在VC++中从DLLMAIN内部调用D3D的CREATEDEVICE时,它会创建一个死锁(loaderlock?)。有没有办法克服这个问题?最终目标内
- 当用2个螺纹锁定时,将recursive_mutex死锁
- 程序在 C++11 中使用条件变量进入死锁
- 一个线程提升的死锁
- 单个生产者/多个消费者死锁
- 当被调用方法使用调用方已锁定的同一锁时,如何避免死锁
- 如何实现无保留和等待以防止死锁