Java Reference
In-Depth Information
}
}
lock. When a thread calls
lock()
and the lock is unavailable, the thread is disabled
(and cannot be scheduled) until the lock becomes available.
This listing also uses
BlockingQueue
's
offer()
method instead of
put()
to
store an object in the blocking queue, and its
poll()
method instead of
take()
to
retrieveanobjectfromthequeue.Thesealternative methodsareusedbecausetheydo
not block.
IfIhadused
put()
and
take()
,thisapplicationwouldhavedeadlockedinthefol-
lowing scenario:
1. The consumer thread acquires the lock via its
lock.lock()
call.
2. The producer thread attempts to acquire the lock via its
lock.lock()
call
and is disabled because the consumer thread has already acquired the lock.
3. The consumer thread calls
take()
to obtain the next
java.lang.Character
object from the queue.
4. Because the queue is empty, the consumer thread must wait.
5. Theconsumerthreaddoesnotgiveupthelockthattheproducerthreadrequires
before waiting, so the producer thread also continues to wait.
Note
If I had access to the private lock used by
BlockingQueue
implementa-
tions, I would have used
put()
and
take()
, and also would have called
Lock
's
lock()
and
unlock()
methodsonthatlock.Theresultingapplication wouldthen
used
synchronized
twice for each of the producer and consumer threads.
Runthisapplicationandyouwilldiscoverthatitgeneratesthesameoutputas
Listing
Atomic Variables
The
java.util.concurrent.atomic
package provides
Atomic
-prefixed
classes (e.g.,
AtomicLong
) that support lock-free, thread-safe operations on single
variables.Eachclassdeclaresmethodssuchas
get()
and
set()
toreadandwritethis
variable without the need for external synchronization.