Java Reference
In-Depth Information
Unlike intrinsic condition queues, you can have as many
Condition
objects per
Lock
as
you want.
Condition
objects inherit the fairness setting of their associated
Lock
; for fair
locks, threads are released from
Condition.await
in FIFO order.
Hazard warning:
The equivalents of
wait
,
notify
, and
notifyAll
for
Condition
objects are
await
,
signal
, and
signalAll
. However,
Condition
extends
Object
,
which means that it also has
wait
and
notify
methods. Be sure to use the proper ver-
sions—
await
and
signal
—instead!
Listing 14.11
shows yet another bounded buffer implementation, this time using two
Condition
s,
notFull
and
notEmpty
, to represent explicitly the “not full” and “not
empty” condition predicates. When
take
blocks because the buffer is empty, it waits on
notEmpty
, and
put
unblocks any threads blocked in
take
by signaling on
notEmpty
.
The behavior of
ConditionBoundedBuffer
is the same as
BoundedBuffer
, but its
use of condition queues is more readable—it is easier to analyze a class that uses multiple
Condition
s than one that uses a single intrinsic condition queue with multiple condition
predicates. By separating the two condition predicates into separate wait sets,
Condition
makes it easier to meet the requirements for single notification. Using the more efficient
signal
instead of
signalAll
reduces the number of context switches and lock acquisi-
tions triggered by each buffer operation.
Just as with built-in locks and condition queues, the three-way relationship among the lock,
the condition predicate, and the condition variable must also hold when using explicit
Lock
s
and
Condition
s. The variables involved in the condition predicate must be guarded by the
Lock
, and the
Lock
must be held when testing the condition predicate and when calling
Choose between using explicit
Condition
s and intrinsic condition queues in the same way
as you would choose between
ReentrantLock
and
synchronized
: use
Condition
if you need its advanced features such as fair queueing or multiple wait sets per lock, and
otherwise prefer intrinsic condition queues. (If you already use
ReentrantLock
because
you need its advanced features, the choice is already made.)