Java Reference
In-Depth Information
Using AQS to build synchronizers offers several benefits. Not only does it substantially re-
duce the implementation effort, but you also needn't pay for multiple points of contention, as
you would when constructing one synchronizer on top of another. In SemaphoreOnLock ,
acquiring a permit has two places where it might block—once at the lock guarding the
semaphore state, and then again if a permit is not available. Synchronizers built with AQS
have only one point where they might block, reducing context-switch overhead and im-
proving
throughput.
AQS
was
designed
for
scalability,
and
all
the
synchronizers
in
java.util.concurrent that are built with AQS benefit from this.
14.5. AbstractQueuedSynchronizer
Most developers will probably never use AQS directly; the standard set of synchronizers cov-
ers a fairly wide range of situations. But seeing how the standard synchronizers are imple-
mented can help clarify how they work.
The basic operations that an AQS-based synchronizer performs are some variants of acquire
and release . Acquisition is the state-dependent operation and can always block. With a lock
or semaphore, the meaning of acquire is straightforward—acquire the lock or a permit—and
the caller may have to wait until the synchronizer is in a state where that can happen. With
CountDownLatch , acquire means “wait until the latch has reached its terminal state”, and
with FutureTask , it means “wait until the task has completed”. Release is not a blocking
operation; a release may allow threads blocked in acquire to proceed.
For a class to be state-dependent, it must have some state. AQS takes on the task of managing
some of the state for the synchronizer class: it manages a single integer of state inform-
ation that can be manipulated through the protected getState , setState , and com-
pareAndSetState methods. This can be used to represent arbitrary state; for example,
ReentrantLock uses it to represent the count of times the owning thread has acquired
the lock, Semaphore uses it to represent the number of permits remaining, and Fu-
tureTask uses it to represent the state of the task (not yet started, running, completed, can-
celled). Synchronizers can also manage additional state variables themselves; for example,
ReentrantLock keeps track of the current lock owner so it can distinguish between
reentrant and contended lock-acquisition requests.
Acquisition and release in AQS take the forms shown in Listing 14.13 . Depending on the
synchronizer, acquisition might be exclusive , as with Reentrant-Lock , or nonexclusive ,
as with Semaphore and CountDownLatch . An acquire operation has two parts. First,
the synchronizer decides whether the current state permits acquisition; if so, the thread is al-
Search WWH ::




Custom Search