Java Reference
In-Depth Information
Because multiple threads could be waiting on the same condition queue for different condi-
tion predicates, using notify instead of notifyAll can be dangerous, primarily because
single notification is prone to a problem akin to missed signals.
BoundedBuffer provides a good illustration of why notifyAll should be preferred to
single notify in most cases. The condition queue is used for two different condition predic-
ates: “not full” and “not empty”. Suppose thread A waits on a condition queue for predicate
PA , while thread B waits on the same condition queue for predicate PB . Now, suppose PB
becomes true and thread C performs a single notify : the JVM will wake up one thread of
its own choosing. If A is chosen, it will wake up, see that PA is not yet true, and go back to
waiting. Meanwhile, B , which could now make progress, does not wake up. This is not ex-
actly a missed signal—it's more of a “hijacked signal”—but the problem is the same: a thread
is waiting for a signal that has (or should have) already occurred.
Single notify can be used instead of notifyAll only when both of the following condi-
tions hold:
Uniform waiters. Only one condition predicate is associated with the condition queue,
and each thread executes the same logic upon returning from wait ; and
One-in, one-out. A notification on the condition variable enables at most one thread to
proceed.
BoundedBuffer meets the one-in, one-out requirement, but does not meet the uniform
waiters requirement because waiting threads might be waiting for either the “not full” and
“not empty” condition. A “starting gate” latch like that used in TestHarness on page 96 ,
in which a single event releases a set of threads, does not meet the one-in, one-out require-
ment because opening the starting gate lets multiple threads proceed.
Most classes don't meet these requirements, so the prevailing wisdom is to use notifyAll
in preference to single notify . While this may be inefficient, it is much easier to ensure
that your classes behave correctly when using notifyAll instead of notify .
This “prevailing wisdom” makes some people uncomfortable, and for good reason. Using
notifyAll when only one thread can make progress is inefficient—sometimes a little,
sometimes grossly so. If ten threads are waiting on a condition queue, calling notifyAll
causes each of them to wake up and contend for the lock; then most or all of them will go
right back to sleep. This means a lot of context switches and a lot of contended lock acquis-
Search WWH ::




Custom Search