美文网首页
JAVA并发之AQS

JAVA并发之AQS

作者: 猿崛起 | 来源:发表于2018-07-30 15:10 被阅读0次

https://www.cnblogs.com/waterystone/p/4920797.html

/**

  • Provides a framework for implementing blocking locks and related
  • synchronizers (semaphores, events, etc) that rely on
  • first-in-first-out (FIFO) wait queues. This class is designed to
  • be a useful basis for most kinds of synchronizers that rely on a
  • single atomic {@code int} value to represent state. Subclasses
  • must define the protected methods that change this state, and which
  • define what that state means in terms of this object being acquired
  • or released. Given these, the other methods in this class carry
  • out all queuing and blocking mechanics. Subclasses can maintain
  • other state fields, but only the atomically updated {@code int}
  • value manipulated using methods {@link #getState}, {@link
  • setState} and {@link #compareAndSetState} is tracked with respect

  • to synchronization.
  • <p>Subclasses should be defined as non-public internal helper
  • classes that are used to implement the synchronization properties
  • of their enclosing class. Class
  • {@code AbstractQueuedSynchronizer} does not implement any
  • synchronization interface. Instead it defines methods such as
  • {@link #acquireInterruptibly} that can be invoked as
  • appropriate by concrete locks and related synchronizers to
  • implement their public methods.
  • <p>This class supports either or both a default <em>exclusive</em>
  • mode and a <em>shared</em> mode. When acquired in exclusive mode,
  • attempted acquires by other threads cannot succeed. Shared mode
  • acquires by multiple threads may (but need not) succeed. This class
  • does not "understand" these differences except in the
  • mechanical sense that when a shared mode acquire succeeds, the next
  • waiting thread (if one exists) must also determine whether it can
  • acquire as well. Threads waiting in the different modes share the
  • same FIFO queue. Usually, implementation subclasses support only
  • one of these modes, but both can come into play for example in a
  • {@link ReadWriteLock}. Subclasses that support only exclusive or
  • only shared modes need not define the methods supporting the unused mode.
  • <p>This class defines a nested {@link ConditionObject} class that
  • can be used as a {@link Condition} implementation by subclasses
  • supporting exclusive mode for which method {@link
  • isHeldExclusively} reports whether synchronization is exclusively

  • held with respect to the current thread, method {@link #release}
  • invoked with the current {@link #getState} value fully releases
  • this object, and {@link #acquire}, given this saved state value,
  • eventually restores this object to its previous acquired state. No
  • {@code AbstractQueuedSynchronizer} method otherwise creates such a
  • condition, so if this constraint cannot be met, do not use it. The
  • behavior of {@link ConditionObject} depends of course on the
  • semantics of its synchronizer implementation.
  • <p>This class provides inspection, instrumentation, and monitoring
  • methods for the internal queue, as well as similar methods for
  • condition objects. These can be exported as desired into classes
  • using an {@code AbstractQueuedSynchronizer} for their
  • synchronization mechanics.
  • <p>Serialization of this class stores only the underlying atomic
  • integer maintaining state, so deserialized objects have empty
  • thread queues. Typical subclasses requiring serializability will
  • define a {@code readObject} method that restores this to a known
  • initial state upon deserialization.
  • <h3>Usage</h3>
  • <p>To use this class as the basis of a synchronizer, redefine the
  • following methods, as applicable, by inspecting and/or modifying
  • the synchronization state using {@link #getState}, {@link
  • setState} and/or {@link #compareAndSetState}:

  • <ul>
  • <li> {@link #tryAcquire}
  • <li> {@link #tryRelease}
  • <li> {@link #tryAcquireShared}
  • <li> {@link #tryReleaseShared}
  • <li> {@link #isHeldExclusively}
  • </ul>
  • Each of these methods by default throws {@link
  • UnsupportedOperationException}. Implementations of these methods
  • must be internally thread-safe, and should in general be short and
  • not block. Defining these methods is the <em>only</em> supported
  • means of using this class. All other methods are declared
  • {@code final} because they cannot be independently varied.
  • <p>You may also find the inherited methods from {@link
  • AbstractOwnableSynchronizer} useful to keep track of the thread
  • owning an exclusive synchronizer. You are encouraged to use them
  • -- this enables monitoring and diagnostic tools to assist users in
  • determining which threads hold locks.
  • <p>Even though this class is based on an internal FIFO queue, it
  • does not automatically enforce FIFO acquisition policies. The core
  • of exclusive synchronization takes the form:
  • <pre>
  • Acquire:
  • while (!tryAcquire(arg)) {
    
  •    <em>enqueue thread if it is not already queued</em>;
    
  •    <em>possibly block current thread</em>;
    
  • }
    
  • Release:
  • if (tryRelease(arg))
    
  •    <em>unblock the first queued thread</em>;
    
  • </pre>
  • (Shared mode is similar but may involve cascading signals.)
  • <p id="barging">Because checks in acquire are invoked before
  • enqueuing, a newly acquiring thread may <em>barge</em> ahead of
  • others that are blocked and queued. However, you can, if desired,
  • define {@code tryAcquire} and/or {@code tryAcquireShared} to
  • disable barging by internally invoking one or more of the inspection
  • methods, thereby providing a <em>fair</em> FIFO acquisition order.
  • In particular, most fair synchronizers can define {@code tryAcquire}
  • to return {@code false} if {@link #hasQueuedPredecessors} (a method
  • specifically designed to be used by fair synchronizers) returns
  • {@code true}. Other variations are possible.
  • <p>Throughput and scalability are generally highest for the
  • default barging (also known as <em>greedy</em>,
  • <em>renouncement</em>, and <em>convoy-avoidance</em>) strategy.
  • While this is not guaranteed to be fair or starvation-free, earlier
  • queued threads are allowed to recontend before later queued
  • threads, and each recontention has an unbiased chance to succeed
  • against incoming threads. Also, while acquires do not
  • "spin" in the usual sense, they may perform multiple
  • invocations of {@code tryAcquire} interspersed with other
  • computations before blocking. This gives most of the benefits of
  • spins when exclusive synchronization is only briefly held, without
  • most of the liabilities when it isn't. If so desired, you can
  • augment this by preceding calls to acquire methods with
  • "fast-path" checks, possibly prechecking {@link #hasContended}
  • and/or {@link #hasQueuedThreads} to only do so if the synchronizer
  • is likely not to be contended.
  • <p>This class provides an efficient and scalable basis for
  • synchronization in part by specializing its range of use to
  • synchronizers that can rely on {@code int} state, acquire, and
  • release parameters, and an internal FIFO wait queue. When this does
  • not suffice, you can build synchronizers from a lower level using
  • {@link java.util.concurrent.atomic atomic} classes, your own custom
  • {@link java.util.Queue} classes, and {@link LockSupport} blocking
  • support.
  • <h3>Usage Examples</h3>
  • <p>Here is a non-reentrant mutual exclusion lock class that uses
  • the value zero to represent the unlocked state, and one to
  • represent the locked state. While a non-reentrant lock
  • does not strictly require recording of the current owner
  • thread, this class does so anyway to make usage easier to monitor.
  • It also supports conditions and exposes
  • one of the instrumentation methods:
  • <pre> {@code
  • class Mutex implements Lock, java.io.Serializable {
  • // Our internal helper class
  • private static class Sync extends AbstractQueuedSynchronizer {
  • // Reports whether in locked state
    
  • protected boolean isHeldExclusively() {
    
  •   return getState() == 1;
    
  • }
    
  • // Acquires the lock if state is zero
    
  • public boolean tryAcquire(int acquires) {
    
  •   assert acquires == 1; // Otherwise unused
    
  •   if (compareAndSetState(0, 1)) {
    
  •     setExclusiveOwnerThread(Thread.currentThread());
    
  •     return true;
    
  •   }
    
  •   return false;
    
  • }
    
  • // Releases the lock by setting state to zero
    
  • protected boolean tryRelease(int releases) {
    
  •   assert releases == 1; // Otherwise unused
    
  •   if (getState() == 0) throw new IllegalMonitorStateException();
    
  •   setExclusiveOwnerThread(null);
    
  •   setState(0);
    
  •   return true;
    
  • }
    
  • // Provides a Condition
    
  • Condition newCondition() { return new ConditionObject(); }
    
  • // Deserializes properly
    
  • private void readObject(ObjectInputStream s)
    
  •     throws IOException, ClassNotFoundException {
    
  •   s.defaultReadObject();
    
  •   setState(0); // reset to unlocked state
    
  • }
    
  • }
  • // The sync object does all the hard work. We just forward to it.
  • private final Sync sync = new Sync();
  • public void lock() { sync.acquire(1); }
  • public boolean tryLock() { return sync.tryAcquire(1); }
  • public void unlock() { sync.release(1); }
  • public Condition newCondition() { return sync.newCondition(); }
  • public boolean isLocked() { return sync.isHeldExclusively(); }
  • public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
  • public void lockInterruptibly() throws InterruptedException {
  • sync.acquireInterruptibly(1);
    
  • }
  • public boolean tryLock(long timeout, TimeUnit unit)
  •   throws InterruptedException {
    
  • return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    
  • }
  • }}</pre>
  • <p>Here is a latch class that is like a
  • {@link java.util.concurrent.CountDownLatch CountDownLatch}
  • except that it only requires a single {@code signal} to
  • fire. Because a latch is non-exclusive, it uses the {@code shared}
  • acquire and release methods.
  • <pre> {@code
  • class BooleanLatch {
  • private static class Sync extends AbstractQueuedSynchronizer {
  • boolean isSignalled() { return getState() != 0; }
    
  • protected int tryAcquireShared(int ignore) {
    
  •   return isSignalled() ? 1 : -1;
    
  • }
    
  • protected boolean tryReleaseShared(int ignore) {
    
  •   setState(1);
    
  •   return true;
    
  • }
    
  • }
  • private final Sync sync = new Sync();
  • public boolean isSignalled() { return sync.isSignalled(); }
  • public void signal() { sync.releaseShared(1); }
  • public void await() throws InterruptedException {
  • sync.acquireSharedInterruptibly(1);
    
  • }
  • }}</pre>

相关文章

网友评论

      本文标题:JAVA并发之AQS

      本文链接:https://www.haomeiwen.com/subject/djzhmftx.html