Java Reference
In-Depth Information
Line 23 in method
blockingPut
calls method
lock
on the
SynchronizedBuffer
's
accessLock
. If the lock is
available
(i.e., no other thread has acquired it), this thread now
owns the lock and the thread continues. If the lock is
unavailable
(i.e., it's held by another
thread), method
lock
waits until the lock is released. After the lock is acquired, lines 26-
46 execute. Line 29 tests
occupied
to determine whether
buffer
is full. If it is, lines 31-
32 display a message indicating that the thread will
wait
. Line 33 calls
Condition
method
await
on the
canWrite
condition object, which temporarily releases the
Synchronized-
Buffer
's
Lock
and
waits
for a signal from the
Consumer
that
buffer
is available for writing.
When
buffer
is available, the method proceeds, writing to
buffer
(line 36), setting
occu-
pied
to
true
(line 40) and displaying a message indicating that the producer wrote a value
(line 42). Line 45 calls
Condition
method
signal
on condition object
canRead
to notify
the waiting
Consumer
(if there is one) that the buffer has new data to be read. Line 49 calls
method
unlock
from a
finally
block to
release
the lock and allow the
Consumer
to pro-
ceed.
Line 57 of method
blockingGet
(lines 54-86) calls method
lock
to
acquire
the
Lock
.
This method
waits
until the
Lock
is
available
. Once the
Lock
is
acquired
, line 63 tests
whether
occupied
is
false
, indicating that the buffer is
empty
. If so, line 67 calls method
await
on condition object
canRead
. Recall that method
signal
is called on variable
can-
Read
in the
blockingPut
method (line 45). When the
Condition
object is
signaled
, the
blockingGet
method continues. Lines 72-74 set
occupied
to
false
, store the value of
buffer
in
readValue
and output the
readValue
. Then line 78
signals
the condition object
canWrite
. This awakens the
Producer
if it's indeed
waiting
for the buffer to be
emptied
.
Line 82 calls method
unlock
from a
finally
block to
release
the lock, and line 85 returns
readValue
to the caller.
Common Programming Error 23.3
Forgetting to
signal
a waiting thread is a logic error. The thread will remain in the
wait-
ing
state, which will prevent it from proceeding. Such waiting can lead to indefinite post-
ponement or deadlock.
Class
SharedBufferTest2
Class
SharedBufferTest2
(Fig. 23.21) is identical to that of Fig. 23.17. Study the outputs
in Fig. 23.21.
Observe that every integer produced is consumed exactly onceāno values are
lost, and no values are consumed more than once.
The
Lock
and
Condition
objects ensure
that the
Producer
and
Consumer
cannot perform their tasks unless it's their turn. The
Pro-
ducer
must
go first, the
Consumer
must wait
if the
Producer
has not produced since the
Consumer
last consumed and the
Producer
must wait
if the
Consumer
has not yet con-
sumed the value that the
Producer
most recently produced. Execute this program several
times to confirm that every integer produced is consumed exactly once. In the sample out-
put, note the highlighted lines indicating when the
Producer
and
Consumer
must
wait
to
perform their respective tasks.
1
// Fig. 23.21: SharedBufferTest2.java
2
// Two threads manipulating a synchronized buffer.
3
import
java.util.concurrent.ExecutorService;
Fig. 23.21
|
Two threads manipulating a synchronized buffer. (Part 1 of 3.)