你搞砸了addPlace
and getPlace
。为了清楚起见,我将它们重命名nextWrite
为nextRead
. 所以这是你的 add()
if ((nextWrite + 1) == nextRead) {
wait();
}
buff[nextWrite] = someRandomNumber;
nextWrite = (nextWrite + 1) % 1000;
notify();
这是你的 get()
if (nextRead == nextWrite) {
wait();
}
逻辑错误很明显:since nextWrite
is in the range [0; 999],nextWrite + 1
将在 [1; 1000],但nextRead
只能在[0;999]。每次 nextWrite
is999
或nextRead
is 0
,wait
调用将永远不会被执行,并且 Producer可能会覆盖尚未读取的数据。
生产者可能会在某个时候停止覆盖,但实际上在一个虚拟的多核机器上,其中一个核心比另一个快一百万倍,生产者将完成其run()
并将终止,因为它仅在nextWrite + 1 == nextRead
.
在我们想象的机器上,Consumer 将立即挂起(因此等于nextRead
,Producer 上次设置的值,因为它运行恰好一百万次迭代,并且您的缓冲区计数器定义为),因为在那一刻它会收到通知Producer,但由于它已终止,因此永远不会收到任何通知。0
nextWrite
0
i % 1000
wait()
这是您的代码的改进(和工作)版本
编辑
我只是忘记了(微不足道的)解决方案:
public synchronized void add(double randomNumber) throws InterruptedException {
if((nextWrite + 1) % 1000 == nextRead)
wait();
buff[nextWrite] = randomNumber;
nextWrite = (nextWrite+1)%1000;
notify();
}