Suj*_*ith 5 c++ mutex deadlock producer-consumer unique-lock
我找到了这个代码,它实现了生产者-消费者问题。我在这里发布一段代码。
在给定的代码中,让我们考虑这样一个场景:生产者通过调用生成一个值void add(int num),它获取互斥体上的锁mu,并且 buffer.size()==size_这使得生产者由于条件变量 而进入等待队列cond。
与此同时,发生上下文切换,消费者调用函数int remove()来消费 value ,它尝试获取 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;
}
}
Run Code Online (Sandbox Code Playgroud)
OutOfBound 的答案很好,但是关于“原子”到底是什么的更多细节是有用的。
对条件变量的操作wait有一个前置条件和一个后置条件,即传入的互斥体被调用者锁定。该wait操作在内部解锁互斥体,并以保证不会错过因解锁互斥体而发生的任何其他线程操作的notify方式进行解锁。notify_all在wait互斥锁的解锁和进入等待通知的状态中,彼此是原子的。这可以避免睡眠/唤醒竞赛。
条件临界区形式在内部测试谓词。然而,这仍然取决于通知是否正确完成。
从某种意义上说,人们可以认为wait这样做:
while (!predicate()) {
mutex.unlock();
/* sleep for a short time or spin */
mutex.lock();
}
Run Code Online (Sandbox Code Playgroud)
带notify的条件变量可以让中间的注释行变得高效。这使:
while (!predicate()) {
atomic { /* This is the key part. */
mutex.unlock();
sleep_until_notified();
}
mutex.lock();
}
Run Code Online (Sandbox Code Playgroud)