让我们考虑以下伪代码:
class OneBuf{
Mutex m;
CondVar cv;
int buffer;
bool full;
void put(int data){
m.lock();
while(full){
cv.wait(m);
}
buffer = data;
full = true;
cv.signal();
m.unlock();
}
int get(){
int data;
m.lock();
while(!full){
cv.wait(m);
}
full = false;
data = buffer;
cv.signal();
m.unlock();
return data;
}
}
有人告诉我,上面的代码是容量为一个整数的缓冲区的错误实现,并且第 14 行和第 26 行应该执行 cv.broadcast() 而不是 cv.signal()。您能否通过显示具有 3 个线程(例如 1 个生产者和 2 个消费者)的初始代码的执行来证明这种更正是必要的,该代码会产生死锁(即所有 3 个线程最终都休眠)?
我不知道我是否需要图论来证明这一点。
如果应用程序处于一个使用者在监视器中而其他两个线程正在等待它的状态,则仅发出信号即可唤醒另一个使用者,该使用者将被阻塞,因为缓冲区现在为空。
而且由于被阻止的消费者没有信号,生产者不会醒来。当缓冲区为空时,第一个使用者最终将被阻塞。
其中一条路径从一个空缓冲区开始(两个使用者都在等待),生产者有两个项目要放入缓冲区。然后,在第二个放置时,它将被阻止,其中一个消费者将进入。