Java Reference
In-Depth Information
14.4. Anatomy of a Synchronizer
The interfaces of
ReentrantLock
and
Semaphore
have a lot in common. Both classes
act as a “gate”, allowing only a limited number of threads to pass at a time; threads arrive at
the gate and are allowed through (
lock
or
acquire
returns successfully), are made to wait
(
lock
or
acquire
blocks), or are turned away (
tryLock
or
tryAcquire
returns false,
indicating that the lock or permit did not become available in the time allowed). Further, both
allow interruptible, uninterruptible, and timed acquisition attempts, and both allow a choice
of fair or nonfair queueing of waiting threads.
Given this commonality, you might think that
Semaphore
was implemented on top of
ReentrantLock
, or perhaps
ReentrantLock
was implemented as a
Semaphore
with
one permit. This would be entirely practical; it is a common exercise to prove that a counting
and that a lock can be implemented using a counting semaphore.
In actuality, they are both implemented using a common base class,
Abstract-
QueuedSynchronizer
(AQS)—as are many other synchronizers. AQS is a framework
for building locks and synchronizers, and a surprisingly broad range of synchronizers can be
built easily and efficiently using it. Not only are
ReentrantLock
and
Semaphore
built
using AQS, but so are
CountDownLatch
,
ReentrantReadWriteLock
,
Synchron-
Listing 14.11. Bounded Buffer Using Explicit Condition Variables.