I am confused a bit by Java's notify()
. The following example is from a textbook.
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();
}
I quite understand the method produce()
in the above example. However, can anyone tell me why we do not use notifyAll()
at the end of the first method (consume()
)? For short, why not like this:
public synchronized consume() {
while(queue.isEmpty()) {
try{ wait(); } catch (InterruptedException e) {}
}
// Assume that getElement() notifies to producers.
element = queue.getElement();
...
notifyAll();
}
Thanks a lot!
Best regards.
I agree with you @Slash. In your code example, since you are removing and element from the queue then someone needs to notify the producers which are waiting in the
isEmpty()
loop. You code however says:So that comment means that somehow
getElement()
callsnotify()
ornotifyAll()
.Yes, your code would work although you need to remove the comment. :-)
Typically in these producer/consumer patterns, there are two locks: one when the queue is empty and one if it is full. Then the consumers can signal the producers when the queue is no longer full and not wake up the other consumers. In this case also, you could use a single
notify()
since you only need to awaken a single consumer or a single producer. ThenotifyAll()
is used here because there is only one object beingsynchronized
on.Also, for posterity, it is very important that you notice the
while()
loops are notif
statements. Even when you are usingnotify()
and two locks there are race conditions in a multiple producer/consumer model that have to be protected against. Also spurious wakeups are an issue. More on that here: