我对Java的notify()
有点困惑。以下示例来自教科书。
public synchronized consume() {
while(queue.isEmpty()) {
try{ wait(); } catch (InterruptedException e) {}
}
// Assume that getElement() notifies to producers.
element = queue.getElement();
...
}
public synchronized produce() {
while(queue.isFull()) {
try{ wait(); } catch (InterruptedException e) {}
}
element = new Element();
...
queue.addElement(element);
notifyAll();
}
我非常了解上面示例中produce()
的方法。但是,谁能告诉我为什么我们不在第一种方法(consume()
)结束时使用notifyAll()
?简而言之,为什么不像这样:
public synchronized consume() {
while(queue.isEmpty()) {
try{ wait(); } catch (InterruptedException e) {}
}
// Assume that getElement() notifies to producers.
element = queue.getElement();
...
notifyAll();
}
多谢!
此致敬意。
我@Slash同意你的看法。 在您的代码示例中,由于您要从队列中删除 and 元素,因此需要有人通知在isEmpty()
循环中等待的生产者。 但是,您的代码说:
// Assume that getElement() notifies to producers.
element = queue.getElement();
所以该评论意味着不知何故getElement()
打电话notify()
或notifyAll()
.
简而言之,为什么不像这样:
是的,尽管您需要删除注释,但您的代码仍然可以工作。 :-)
通常在这些生产者/使用者模式中,有两个锁:一个在队列为空时,另一个在队列已满时。 然后,当队列不再已满时,使用者可以向生产者发出信号,而不会唤醒其他使用者。 在这种情况下,您也可以使用单个notify()
因为您只需要唤醒单个使用者或单个生产者。 此处使用notifyAll()
是因为只有一个对象synchronized
。
此外,对于后代来说,注意while()
循环不是if
语句非常重要。 即使使用notify()
和两个锁,也必须保护多生产者/使用者模型中的争用条件。 虚假唤醒也是一个问题。 更多关于这里:
http://256stuff.com/gray/docs/misc/producer_consumer_race_conditions/
在这种情况下,在生产时使用通知,告诉消费者现在有东西要消费,以便其中一个可以唤醒并消费它。
当消费者刚刚消费了某些东西时通知假设发生在getElement()中:
// Assume that getElement() notifies to producers.