java中锁的介绍

介绍锁之前,需要先熟悉一个非常重要的组件,掌握了该组件JUC包下面很多问题都不在是问题了。该组件就是AQS。

(1) AQS:
AbstractQueuedSynchronizer,即队列同步器。它是构建锁或者其他同步组件的基础框架(如ReentrantLock、ReentrantReadWriteLock、Semaphore等),JUC并发包的作者(Doug Lea)期望它能够成为实现大部分同步需求的基础。它是JUC并发包中的核心基础组件。

AQS的主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状态。使用int类型的成员变量state来表示同步状态,当state>0时表示已经获取了锁,当state = 0时表示释放了锁。它提供了三个方法(getState()、setState(int newState)、compareAndSetState(int expe ct,int update))来对同步状态state进行操作,当然AQS可以确保对state的操作是安全的。

AQS的设计模式采用的模板方法模式,子类通过继承的方式,实现它的抽象方法来管理同步状态,对于子类而言它并没有太多的活要做,AQS提供了大量的模板方法来实现同步,主要是分为三类:

1):独占式获取和释放同步状态
同一时刻仅有一个线程持有同步状态。 acquire(int arg)方法为AQS提供的模板方法,该方法为独占式获取同步状态,但是该方法对中断不敏感,也就是说由于线程获取同步状态失败加入到CLH同步队列中,后续对线程进行中断操作时,线程不会从同步队列中移除。代码如下:

public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
2):共享式获取和释放同步状态 ->
3):查询同步队列中的等待线程情况。
4)常用方法
getState():返回同步状态的当前值;

setState(int newState):设置当前同步状态;

compareAndSetState(int expect, int update):使用CAS设置当前状态,该方法能够保证状态设置的原子性;

tryAcquire(int arg):独占式获取同步状态,获取同步状态成功后,其他线程需要等待该线程释放同步状态才能获取同步状态

tryRelease(int arg):独占式释放同步状态;

tryAcquireShared(int arg):共享式获取同步状态,返回值大于等于0则表示获取成功,否则获取失败;

tryReleaseShared(int arg):共享式释放同步状态;

isHeldExclusively():当前同步器是否在独占式模式下被线程占用,一般该方法表示是否被当前线程所独占;

acquire(int arg):独占式获取同步状态,如果当前线程获取同步状态成功,则由该方法返回,否则,将会进入同步队列等待,该方法将会调用可重写的tryAcquire(int arg)方法;

acquireInterruptibly(int arg):与acquire(int arg)相同,但是该方法响应中断,当前线程为获取到同步状态而进入到同步队列中,如果当前线程被中断,则该方法会抛出InterruptedException异常并返回;

tryAcquireNanos(int arg,long nanos):超时获取同步状态,如果当前线程在nanos时间内没有获取到同步状态,那么将会返回false,已经获取则返回true;

acquireShared(int arg):共享式获取同步状态,如果当前线程未获取到同步状态,将会进入同步队列等待,与独占式的主要区别是在同一时刻可以有多个线程获取到同步状态;

acquireSharedInterruptibly(int arg):共享式获取同步状态,响应中断;

tryAcquireSharedNanos(int arg, long nanosTimeout):共享式获取同步状态,增加超时限制;

release(int arg):独占式释放同步状态,该方法会在释放同步状态之后,将同步队列中第一个节点包含的线程唤醒;

releaseShared(int arg):共享式释放同步状态;

2)CLH同步队列(用来在等待获取锁的队列)
CLH同步队列是一个FIFO双向队列,AQS通过内置的FIFO同步队列依赖它来完成同步状态的管理,当前线程如果获取同步状态失败时,AQS则会将当前线程已经等待状态等信息构造成一个节点(Node)并将其加入到CLH同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点唤醒(公平锁),使其再次尝试获取同步状态。

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer
implements java.io.Serializable {
private transient volatile Node head;
/**
* Tail of the wait queue, lazily initialized. Modified only via
* method enq to add new wait node.
/
private transient volatile Node tail;
/
*
* The synchronization state.
/
private volatile int state;

/
*
* Returns the current value of synchronization state.
* This operation has memory semantics of a {@code volatile} read.
* @return current state value
/
protected final int getState() {
return state;
}
/
*
* Sets the value of synchronization state.
* This operation has memory semantics of a {@code volatile} write.
* @param newState the new state value
/
protected final void setState(int newState) {
state = newState;
}
/
*
* Atomically sets synchronization state to the given updated
* value if the current state value equals the expected value.
* This operation has memory semantics of a {@code volatile} read
* and write.
*
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful. False return indicates that the actual
* value was not equal to the expected value.
*/
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
}
3)获取锁过程
我们从这开始

public class test {
public static void main(String[] args) throws Exception {
final int[] counter = {0};
ReentrantLock lock = new ReentrantLock();
for (int i = 0; i < 50; i++) {
new Thread(new Runnable() {
@Override
public void run() {
lock.lock();//获取锁
try {
int a = counter[0];
counter[0] = a + 1;
} finally {
lock.unlock();
}
}
}).start();
} // 主线程休眠,等待结果 Thread.sleep(5000); System.out.println(counter[0]); }}
}
}

/*
*

  • Written by Doug Lea with assistance from members of JCP JSR-166
  • Expert Group and released to the public domain, as explained at
  • http://creativecommons.org/publicdomain/zero/1.0/
    /

    package java.util.concurrent.locks;
    import java.util.concurrent.TimeUnit;
    import java.util.Collection;

    /
    *
  • A reentrant mutual exclusion {@link Lock} with the same basic
  • behavior and semantics as the implicit monitor lock accessed using
  • {@code synchronized} methods and statements, but with extended
  • capabilities.
  • A {@code ReentrantLock} is owned by the thread last

  • successfully locking, but not yet unlocking it. A thread invoking
  • {@code lock} will return, successfully acquiring the lock, when
  • the lock is not owned by another thread. The method will return
  • immediately if the current thread already owns the lock. This can
  • be checked using methods {@link #isHeldByCurrentThread}, and {@link
  • #getHoldCount}.
  • The constructor for this class accepts an optional

  • fairness parameter. When set {@code true}, under
  • contention, locks favor granting access to the longest-waiting
  • thread. Otherwise this lock does not guarantee any particular
  • access order. Programs using fair locks accessed by many threads
  • may display lower overall throughput (i.e., are slower; often much
  • slower) than those using the default setting, but have smaller
  • variances in times to obtain locks and guarantee lack of
  • starvation. Note however, that fairness of locks does not guarantee
  • fairness of thread scheduling. Thus, one of many threads using a
  • fair lock may obtain it multiple times in succession while other
  • active threads are not progressing and not currently holding the
  • lock.
  • Also note that the untimed {@link #tryLock()} method does not
  • honor the fairness setting. It will succeed if the lock
  • is available even if other threads are waiting.
  • It is recommended practice to always immediately

  • follow a call to {@code lock} with a {@code try} block, most
  • typically in a before/after construction such as:
  •  {@code
    
  • class X {
  • private final ReentrantLock lock = new ReentrantLock();
  • // …
  • public void m() {
  • lock.lock();  // block until condition holds
    
  • try {
    
  •   // ... method body
    
  • } finally {
    
  •   lock.unlock()
    
  • }
    
  • }
  • }}
  • In addition to implementing the {@link Lock} interface, this

  • class defines a number of {@code public} and {@code protected}
  • methods for inspecting the state of the lock. Some of these
  • methods are only useful for instrumentation and monitoring.
  • Serialization of this class behaves in the same way as built-in

  • locks: a deserialized lock is in the unlocked state, regardless of
  • its state when serialized.
  • This lock supports a maximum of 2147483647 recursive locks by

  • the same thread. Attempts to exceed this limit result in
  • {@link Error} throws from locking methods.
  • @since 1.5
  • @author Doug Lea
    /
    public class ReentrantLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = 7373984872572414699L;
    /
    * Synchronizer providing all implementation mechanics /
    private final Sync sync;

    /
    *
    • Base of synchronization control for this lock. Subclassed
    • into fair and nonfair versions below. Uses AQS state to
    • represent the number of holds on the lock.
      /
      abstract static class Sync extends AbstractQueuedSynchronizer {
      private static final long serialVersionUID = -5179523762034025860L;

      /
      *
      • Performs {@link Lock#lock}. The main reason for subclassing
      • is to allow fast path for nonfair version.
        /
        abstract void lock();

        /
        *
      • Performs non-fair tryLock. tryAcquire is implemented in
      • subclasses, but both need nonfair try for trylock method.
        /
        final boolean nonfairTryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) {
        if (compareAndSetState(0, acquires)) {
        setExclusiveOwnerThread(current);
        return true;
        }
        }
        else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0) // overflow
        throw new Error(“Maximum lock count exceeded”);
        setState(nextc);
        return true;
        }
        return false;
        }

        protected final boolean tryRelease(int releases) {
        int c = getState() - releases;
        if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
        boolean free = false;
        if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
        }
        setState©;
        return free;
        }

        protected final boolean isHeldExclusively() {
        // While we must in general read state before owner,
        // we don’t need to do so to check if current thread is owner
        return getExclusiveOwnerThread() == Thread.currentThread();
        }

        final ConditionObject newCondition() {
        return new ConditionObject();
        }

        // Methods relayed from outer class

        final Thread getOwner() {
        return getState() == 0 ? null : getExclusiveOwnerThread();
        }

        final int getHoldCount() {
        return isHeldExclusively() ? getState() : 0;
        }

        final boolean isLocked() {
        return getState() != 0;
        }

        /
        *
      • Reconstitutes the instance from a stream (that is, deserializes it).
        /
        private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        s.defaultReadObject();
        setState(0); // reset to unlocked state
        }
        }

        /
        *
    • Sync object for non-fair locks
      /
      static final class NonfairSync extends Sync {
      private static final long serialVersionUID = 7316153563782823691L;

      /
      *
      • Performs lock. Try immediate barge, backing up to normal
      • acquire on failure.
        /
        final void lock() {
        if (compareAndSetState(0, 1))
        setExclusiveOwnerThread(Thread.currentThread());
        else
        acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
        }
        }

        /
        *
    • Sync object for fair locks
      /
      static final class FairSync extends Sync {
      private static final long serialVersionUID = -3000897897090466540L;

      final void lock() {
      acquire(1);
      }

      /
      *
      • Fair version of tryAcquire. Don’t grant access unless
      • recursive call or no waiters or is first.
        /
        protected final boolean tryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) {
        if (!hasQueuedPredecessors() &&
        compareAndSetState(0, acquires)) {
        setExclusiveOwnerThread(current);
        return true;
        }
        }
        else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0)
        throw new Error(“Maximum lock count exceeded”);
        setState(nextc);
        return true;
        }
        return false;
        }
        }

        /
        *
    • Creates an instance of {@code ReentrantLock}.
    • This is equivalent to using {@code ReentrantLock(false)}.
      /
      public ReentrantLock() {
      sync = new NonfairSync();//说明默认调用的是非公平锁
      }

      /
      *
    • Creates an instance of {@code ReentrantLock} with the
    • given fairness policy.
    • @param fair {@code true} if this lock should use a fair ordering policy
      /
      public ReentrantLock(boolean fair) {
      sync = fair ? new FairSync() : new NonfairSync();
      }

      /
      *
    • Acquires the lock.
    • Acquires the lock if it is not held by another thread and returns

    • immediately, setting the lock hold count to one.
    • If the current thread already holds the lock then the hold

    • count is incremented by one and the method returns immediately.
    • If the lock is held by another thread then the

    • current thread becomes disabled for thread scheduling
    • purposes and lies dormant until the lock has been acquired,
    • at which time the lock hold count is set to one.
      /
      public void lock() {
      sync.lock();
      }

      /
      *
    • Acquires the lock unless the current thread is
    • {@linkplain Thread#interrupt interrupted}.
    • Acquires the lock if it is not held by another thread and returns

    • immediately, setting the lock hold count to one.
    • If the current thread already holds this lock then the hold count

    • is incremented by one and the method returns immediately.
    • If the lock is held by another thread then the

    • current thread becomes disabled for thread scheduling
    • purposes and lies dormant until one of two things happens:
      • The lock is acquired by the current thread; or
      • Some other thread {@linkplain Thread#interrupt interrupts} the
      • current thread.
    • If the lock is acquired by the current thread then the lock hold

    • count is set to one.
    • If the current thread:

      • has its interrupted status set on entry to this method; or
      • is {@linkplain Thread#interrupt interrupted} while acquiring
      • the lock,
      • then {@link InterruptedException} is thrown and the current thread’s
      • interrupted status is cleared.
      • In this implementation, as this method is an explicit

      • interruption point, preference is given to responding to the
      • interrupt over normal or reentrant acquisition of the lock.
      • @throws InterruptedException if the current thread is interrupted
        /
        public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
        }

        /
        *
      • Acquires the lock only if it is not held by another thread at the time
      • of invocation.
      • Acquires the lock if it is not held by another thread and

      • returns immediately with the value {@code true}, setting the
      • lock hold count to one. Even when this lock has been set to use a
      • fair ordering policy, a call to {@code tryLock()} will
      • immediately acquire the lock if it is available, whether or not
      • other threads are currently waiting for the lock.
      • This "barging" behavior can be useful in certain
      • circumstances, even though it breaks fairness. If you want to honor
      • the fairness setting for this lock, then use
      • {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
      • which is almost equivalent (it also detects interruption).
      • If the current thread already holds this lock then the hold

      • count is incremented by one and the method returns {@code true}.
      • If the lock is held by another thread then this method will return

      • immediately with the value {@code false}.
      • @return {@code true} if the lock was free and was acquired by the
      •     current thread, or the lock was already held by the current
        
      •     thread; and {@code false} otherwise
        
      • /
        public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
        }

        /
        *
        • Acquires the lock if it is not held by another thread within the given
        • waiting time and the current thread has not been
        • {@linkplain Thread#interrupt interrupted}.
        • Acquires the lock if it is not held by another thread and returns

        • immediately with the value {@code true}, setting the lock hold count
        • to one. If this lock has been set to use a fair ordering policy then
        • an available lock will not be acquired if any other threads
        • are waiting for the lock. This is in contrast to the {@link #tryLock()}
        • method. If you want a timed {@code tryLock} that does permit barging on
        • a fair lock then combine the timed and un-timed forms together:
        •  {@code
          
        • if (lock.tryLock() ||
        • lock.tryLock(timeout, unit)) {
          
        • }}
        • If the current thread

        • already holds this lock then the hold count is incremented by one and
        • the method returns {@code true}.
        • If the lock is held by another thread then the

        • current thread becomes disabled for thread scheduling
        • purposes and lies dormant until one of three things happens:
          • The lock is acquired by the current thread; or
          • Some other thread {@linkplain Thread#interrupt interrupts}
          • the current thread; or
          • The specified waiting time elapses
        • If the lock is acquired then the value {@code true} is returned and

        • the lock hold count is set to one.
        • If the current thread:

          • has its interrupted status set on entry to this method; or
          • is {@linkplain Thread#interrupt interrupted} while
          • acquiring the lock,
          • then {@link InterruptedException} is thrown and the current thread’s
          • interrupted status is cleared.
          • If the specified waiting time elapses then the value {@code false}

          • is returned. If the time is less than or equal to zero, the method
          • will not wait at all.
          • In this implementation, as this method is an explicit

          • interruption point, preference is given to responding to the
          • interrupt over normal or reentrant acquisition of the lock, and
          • over reporting the elapse of the waiting time.
          • @param timeout the time to wait for the lock
          • @param unit the time unit of the timeout argument
          • @return {@code true} if the lock was free and was acquired by the
          •     current thread, or the lock was already held by the current
            
          •     thread; and {@code false} if the waiting time elapsed before
            
          •     the lock could be acquired
            
          • @throws InterruptedException if the current thread is interrupted
          • @throws NullPointerException if the time unit is null
            /
            public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
            }

            /
            *
          • Attempts to release this lock.
          • If the current thread is the holder of this lock then the hold

          • count is decremented. If the hold count is now zero then the lock
          • is released. If the current thread is not the holder of this
          • lock then {@link IllegalMonitorStateException} is thrown.
          • @throws IllegalMonitorStateException if the current thread does not
          •     hold this lock
            
          • /
            public void unlock() {
            sync.release(1);
            }

            /
            *
            • Returns a {@link Condition} instance for use with this
            • {@link Lock} instance.
            • The returned {@link Condition} instance supports the same

            • usages as do the {@link Object} monitor methods ({@link
            • Object#wait() wait}, {@link Object#notify notify}, and {@link
            • Object#notifyAll notifyAll}) when used with the built-in
            • monitor lock.
              • If this lock is not held when any of the {@link Condition}
              • {@linkplain Condition#await() waiting} or {@linkplain
              • Condition#signal signalling} methods are called, then an {@link
              • IllegalMonitorStateException} is thrown.
              • When the condition {@linkplain Condition#await() waiting}
              • methods are called the lock is released and, before they
              • return, the lock is reacquired and the lock hold count restored
              • to what it was when the method was called.
              • If a thread is {@linkplain Thread#interrupt interrupted}
              • while waiting then the wait will terminate, an {@link
              • InterruptedException} will be thrown, and the thread’s
              • interrupted status will be cleared.
              • Waiting threads are signalled in FIFO order.
              • The ordering of lock reacquisition for threads returning
              • from waiting methods is the same as for threads initially
              • acquiring the lock, which is in the default case not specified,
              • but for fair locks favors those threads that have been
              • waiting the longest.
            • @return the Condition object
              /
              public Condition newCondition() {
              return sync.newCondition();
              }

              /
              *
            • Queries the number of holds on this lock by the current thread.
            • A thread has a hold on a lock for each lock action that is not

            • matched by an unlock action.
            • The hold count information is typically only used for testing and

            • debugging purposes. For example, if a certain section of code should
            • not be entered with the lock already held then we can assert that
            • fact:
            •  {@code
              
            • class X {
            • ReentrantLock lock = new ReentrantLock();
            • // …
            • public void m() {
            • assert lock.getHoldCount() == 0;
              
            • lock.lock();
              
            • try {
              
            •   // ... method body
              
            • } finally {
              
            •   lock.unlock();
              
            • }
              
            • }
            • }}
            • @return the number of holds on this lock by the current thread,
            •     or zero if this lock is not held by the current thread
              
            • /
              public int getHoldCount() {
              return sync.getHoldCount();
              }

              /
              *
              • Queries if this lock is held by the current thread.
              • Analogous to the {@link Thread#holdsLock(Object)} method for

              • built-in monitor locks, this method is typically used for
              • debugging and testing. For example, a method that should only be
              • called while a lock is held can assert that this is the case:
              •  {@code
                
              • class X {
              • ReentrantLock lock = new ReentrantLock();
              • // …
              • public void m() {
              •   assert lock.isHeldByCurrentThread();
                
              •   // ... method body
                
              • }
              • }}
              • It can also be used to ensure that a reentrant lock is used

              • in a non-reentrant manner, for example:
              •  {@code
                
              • class X {
              • ReentrantLock lock = new ReentrantLock();
              • // …
              • public void m() {
              •   assert !lock.isHeldByCurrentThread();
                
              •   lock.lock();
                
              •   try {
                
              •       // ... method body
                
              •   } finally {
                
              •       lock.unlock();
                
              •   }
                
              • }
              • }}
              • @return {@code true} if current thread holds this lock and
              •     {@code false} otherwise
                
              /
              public boolean isHeldByCurrentThread() {
              return sync.isHeldExclusively();
              }

              /
              *
              • Queries if this lock is held by any thread. This method is
              • designed for use in monitoring of the system state,
              • not for synchronization control.
              • @return {@code true} if any thread holds this lock and
              •     {@code false} otherwise
                
              /
              public boolean isLocked() {
              return sync.isLocked();
              }

              /
              *
              • Returns {@code true} if this lock has fairness set true.
              • @return {@code true} if this lock has fairness set true
                /
                public final boolean isFair() {
                return sync instanceof FairSync;
                }

                /
                *
              • Returns the thread that currently owns this lock, or
              • {@code null} if not owned. When this method is called by a
              • thread that is not the owner, the return value reflects a
              • best-effort approximation of current lock status. For example,
              • the owner may be momentarily {@code null} even if there are
              • threads trying to acquire the lock but have not yet done so.
              • This method is designed to facilitate construction of
              • subclasses that provide more extensive lock monitoring
              • facilities.
              • @return the owner, or {@code null} if not owned
                /
                protected Thread getOwner() {
                return sync.getOwner();
                }

                /
                *
              • Queries whether any threads are waiting to acquire this lock. Note that
              • because cancellations may occur at any time, a {@code true}
              • return does not guarantee that any other thread will ever
              • acquire this lock. This method is designed primarily for use in
              • monitoring of the system state.
              • @return {@code true} if there may be other threads waiting to
              •     acquire the lock
                
              /
              public final boolean hasQueuedThreads() {
              return sync.hasQueuedThreads();
              }

              /
              *
              • Queries whether the given thread is waiting to acquire this
              • lock. Note that because cancellations may occur at any time, a
              • {@code true} return does not guarantee that this thread
              • will ever acquire this lock. This method is designed primarily for use
              • in monitoring of the system state.
              • @param thread the thread
              • @return {@code true} if the given thread is queued waiting for this lock
              • @throws NullPointerException if the thread is null
                /
                public final boolean hasQueuedThread(Thread thread) {
                return sync.isQueued(thread);
                }

                /
                *
              • Returns an estimate of the number of threads waiting to
              • acquire this lock. The value is only an estimate because the number of
              • threads may change dynamically while this method traverses
              • internal data structures. This method is designed for use in
              • monitoring of the system state, not for synchronization
              • control.
              • @return the estimated number of threads waiting for this lock
                /
                public final int getQueueLength() {
                return sync.getQueueLength();
                }

                /
                *
              • Returns a collection containing threads that may be waiting to
              • acquire this lock. Because the actual set of threads may change
              • dynamically while constructing this result, the returned
              • collection is only a best-effort estimate. The elements of the
              • returned collection are in no particular order. This method is
              • designed to facilitate construction of subclasses that provide
              • more extensive monitoring facilities.
              • @return the collection of threads
                /
                protected Collection getQueuedThreads() {
                return sync.getQueuedThreads();
                }

                /
                *
              • Queries whether any threads are waiting on the given condition
              • associated with this lock. Note that because timeouts and
              • interrupts may occur at any time, a {@code true} return does
              • not guarantee that a future {@code signal} will awaken any
              • threads. This method is designed primarily for use in
              • monitoring of the system state.
              • @param condition the condition
              • @return {@code true} if there are any waiting threads
              • @throws IllegalMonitorStateException if this lock is not held
              • @throws IllegalArgumentException if the given condition is
              •     not associated with this lock
                
              • @throws NullPointerException if the condition is null
                /
                public boolean hasWaiters(Condition condition) {
                if (condition == null)
                throw new NullPointerException();
                if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException(“not owner”);
                return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
                }

                /
                *
              • Returns an estimate of the number of threads waiting on the
              • given condition associated with this lock. Note that because
              • timeouts and interrupts may occur at any time, the estimate
              • serves only as an upper bound on the actual number of waiters.
              • This method is designed for use in monitoring of the system
              • state, not for synchronization control.
              • @param condition the condition
              • @return the estimated number of waiting threads
              • @throws IllegalMonitorStateException if this lock is not held
              • @throws IllegalArgumentException if the given condition is
              •     not associated with this lock
                
              • @throws NullPointerException if the condition is null
                /
                public int getWaitQueueLength(Condition condition) {
                if (condition == null)
                throw new NullPointerException();
                if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException(“not owner”);
                return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
                }

                /
                *
              • Returns a collection containing those threads that may be
              • waiting on the given condition associated with this lock.
              • Because the actual set of threads may change dynamically while
              • constructing this result, the returned collection is only a
              • best-effort estimate. The elements of the returned collection
              • are in no particular order. This method is designed to
              • facilitate construction of subclasses that provide more
              • extensive condition monitoring facilities.
              • @param condition the condition
              • @return the collection of threads
              • @throws IllegalMonitorStateException if this lock is not held
              • @throws IllegalArgumentException if the given condition is
              •     not associated with this lock
                
              • @throws NullPointerException if the condition is null
                /
                protected Collection getWaitingThreads(Condition condition) {
                if (condition == null)
                throw new NullPointerException();
                if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException(“not owner”);
                return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
                }

                /
                *
              • Returns a string identifying this lock, as well as its lock state.
              • The state, in brackets, includes either the String {@code “Unlocked”}
              • or the String {@code “Locked by”} followed by the
              • {@linkplain Thread#getName name} of the owning thread.
              • @return a string identifying this lock, as well as its lock state
                */
                public String toString() {
                Thread o = sync.getOwner();
                return super.toString() + ((o == null) ?
                “[Unlocked]” :
                "[Locked by thread " + o.getName() + “]”);
                }
                }

                我们能发现, lock.lock()默认调用的是NonfairSync 中的lock;NonfairSync 又是继承于Sync,一步一步往上找,找到了这个鬼AbstractQueuedSynchronizer(简称AQS),Sync继承AbstractQueuedSynchronizer,最后这个鬼,又是继承于AbstractOwnableSynchronizer(AOS),AOS主要是保存获取当前锁的线程对象。

              /*

              • ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
                /

                /
              • Written by Doug Lea with assistance from members of JCP JSR-166
              • Expert Group and released to the public domain, as explained at
              • http://creativecommons.org/publicdomain/zero/1.0/
                /

                package java.util.concurrent.locks;
                import java.util.concurrent.TimeUnit;
                import java.util.ArrayList;
                import java.util.Collection;
                import java.util.Date;
                import sun.misc.Unsafe;

                /
                *
              • 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.
              • 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.
              • This class supports either or both a default exclusive

              • mode and a shared 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.
              • 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.
              • 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.
              • 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.
              • Usage

              • 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}:
                • {@link #tryAcquire}
                • {@link #tryRelease}
                • {@link #tryAcquireShared}
                • {@link #tryReleaseShared}
                • {@link #isHeldExclusively}
              • 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 only supported
              • means of using this class. All other methods are declared
              • {@code final} because they cannot be independently varied.
              • 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.
              • 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:
              • 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>;
                
              • (Shared mode is similar but may involve cascading signals.)
              • Because checks in acquire are invoked before

              • enqueuing, a newly acquiring thread may barge 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 fair 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.
              • Throughput and scalability are generally highest for the

              • default barging (also known as greedy,
              • renouncement, and convoy-avoidance) 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.
              • 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.
              • Usage Examples

              • 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:
              •  {@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));
                
              • }
              • }}
              • 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.
              •  {@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);
                
              • }
              • }}
              • @since 1.5
              • @author Doug Lea
                /
                public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer
                implements java.io.Serializable {

                private static final long serialVersionUID = 7373984972572414691L;

                /
                *
                • Creates a new {@code AbstractQueuedSynchronizer} instance
                • with initial synchronization state of zero.
                  /
                  protected AbstractQueuedSynchronizer() { }

                  /
                  *
                • Wait queue node class.
                • The wait queue is a variant of a "CLH" (Craig, Landin, and

                • Hagersten) lock queue. CLH locks are normally used for
                • spinlocks. We instead use them for blocking synchronizers, but
                • use the same basic tactic of holding some of the control
                • information about a thread in the predecessor of its node. A
                • “status” field in each node keeps track of whether a thread
                • should block. A node is signalled when its predecessor
                • releases. Each node of the queue otherwise serves as a
                • specific-notification-style monitor holding a single waiting
                • thread. The status field does NOT control whether threads are
                • granted locks etc though. A thread may try to acquire if it is
                • first in the queue. But being first does not guarantee success;
                • it only gives the right to contend. So the currently released
                • contender thread may need to rewait.
                • To enqueue into a CLH lock, you atomically splice it in as new

                • tail. To dequeue, you just set the head field.
                •  +------+  prev +-----+       +-----+
                  
                • head | | <---- | | <---- | | tail
                •  +------+       +-----+       +-----+
                  
                • Insertion into a CLH queue requires only a single atomic

                • operation on “tail”, so there is a simple atomic point of
                • demarcation from unqueued to queued. Similarly, dequeuing
                • involves only updating the “head”. However, it takes a bit
                • more work for nodes to determine who their successors are,
                • in part to deal with possible cancellation due to timeouts
                • and interrupts.
                • The "prev" links (not used in original CLH locks), are mainly

                • needed to handle cancellation. If a node is cancelled, its
                • successor is (normally) relinked to a non-cancelled
                • predecessor. For explanation of similar mechanics in the case
                • of spin locks, see the papers by Scott and Scherer at
                • http://www.cs.rochester.edu/u/scott/synchronization/
                • We also use "next" links to implement blocking mechanics.

                • The thread id for each node is kept in its own node, so a
                • predecessor signals the next node to wake up by traversing
                • next link to determine which thread it is. Determination of
                • successor must avoid races with newly queued nodes to set
                • the “next” fields of their predecessors. This is solved
                • when necessary by checking backwards from the atomically
                • updated “tail” when a node’s successor appears to be null.
                • (Or, said differently, the next-links are an optimization
                • so that we don’t usually need a backward scan.)
                • Cancellation introduces some conservatism to the basic

                • algorithms. Since we must poll for cancellation of other
                • nodes, we can miss noticing whether a cancelled node is
                • ahead or behind us. This is dealt with by always unparking
                • successors upon cancellation, allowing them to stabilize on
                • a new predecessor, unless we can identify an uncancelled
                • predecessor who will carry this responsibility.
                • CLH queues need a dummy header node to get started. But

                • we don’t create them on construction, because it would be wasted
                • effort if there is never contention. Instead, the node
                • is constructed and head and tail pointers are set upon first
                • contention.
                • Threads waiting on Conditions use the same nodes, but

                • use an additional link. Conditions only need to link nodes
                • in simple (non-concurrent) linked queues because they are
                • only accessed when exclusively held. Upon await, a node is
                • inserted into a condition queue. Upon signal, the node is
                • transferred to the main queue. A special value of status
                • field is used to mark which queue a node is on.
                • Thanks go to Dave Dice, Mark Moir, Victor Luchangco, Bill

                • Scherer and Michael Scott, along with members of JSR-166
                • expert group, for helpful ideas, discussions, and critiques
                • on the design of this class.
                  /
                  static final class Node {
                  /
                  * Marker to indicate a node is waiting in shared mode /
                  static final Node SHARED = new Node();
                  /
                  * Marker to indicate a node is waiting in exclusive mode /
                  static final Node EXCLUSIVE = null;

                  /
                  * waitStatus value to indicate thread has cancelled /
                  static final int CANCELLED = 1;
                  /
                  * waitStatus value to indicate successor’s thread needs unparking /
                  static final int SIGNAL = -1;
                  /
                  * waitStatus value to indicate thread is waiting on condition /
                  static final int CONDITION = -2;
                  /
                  *
                  • waitStatus value to indicate the next acquireShared should
                  • unconditionally propagate
                    /
                    static final int PROPAGATE = -3;

                    /
                    *
                  • Status field, taking on only the values:
                  • SIGNAL: The successor of this node is (or will soon be)
                  •           blocked (via park), so the current node must
                    
                  •           unpark its successor when it releases or
                    
                  •           cancels. To avoid races, acquire methods must
                    
                  •           first indicate they need a signal,
                    
                  •           then retry the atomic acquire, and then,
                    
                  •           on failure, block.
                    
                  • CANCELLED: This node is cancelled due to timeout or interrupt.
                  •           Nodes never leave this state. In particular,
                    
                  •           a thread with cancelled node never again blocks.
                    
                  • CONDITION: This node is currently on a condition queue.
                  •           It will not be used as a sync queue node
                    
                  •           until transferred, at which time the status
                    
                  •           will be set to 0. (Use of this value here has
                    
                  •           nothing to do with the other uses of the
                    
                  •           field, but simplifies mechanics.)
                    
                  • PROPAGATE: A releaseShared should be propagated to other
                  •           nodes. This is set (for head node only) in
                    
                  •           doReleaseShared to ensure propagation
                    
                  •           continues, even if other operations have
                    
                  •           since intervened.
                    
                  • 0: None of the above
                  • The values are arranged numerically to simplify use.
                  • Non-negative values mean that a node doesn’t need to
                  • signal. So, most code doesn’t need to check for particular
                  • values, just for sign.
                  • The field is initialized to 0 for normal sync nodes, and
                  • CONDITION for condition nodes. It is modified using CAS
                  • (or when possible, unconditional volatile writes).
                    /
                    volatile int waitStatus;

                    /
                    *
                  • Link to predecessor node that current node/thread relies on
                  • for checking waitStatus. Assigned during enqueuing, and nulled
                  • out (for sake of GC) only upon dequeuing. Also, upon
                  • cancellation of a predecessor, we short-circuit while
                  • finding a non-cancelled one, which will always exist
                  • because the head node is never cancelled: A node becomes
                  • head only as a result of successful acquire. A
                  • cancelled thread never succeeds in acquiring, and a thread only
                  • cancels itself, not any other node.
                    /
                    volatile Node prev;

                    /
                    *
                  • Link to the successor node that the current node/thread
                  • unparks upon release. Assigned during enqueuing, adjusted
                  • when bypassing cancelled predecessors, and nulled out (for
                  • sake of GC) when dequeued. The enq operation does not
                  • assign next field of a predecessor until after attachment,
                  • so seeing a null next field does not necessarily mean that
                  • node is at end of queue. However, if a next field appears
                  • to be null, we can scan prev’s from the tail to
                  • double-check. The next field of cancelled nodes is set to
                  • point to the node itself instead of null, to make life
                  • easier for isOnSyncQueue.
                    /
                    volatile Node next;

                    /
                    *
                  • The thread that enqueued this node. Initialized on
                  • construction and nulled out after use.
                    /
                    volatile Thread thread;

                    /
                    *
                  • Link to next node waiting on condition, or the special
                  • value SHARED. Because condition queues are accessed only
                  • when holding in exclusive mode, we just need a simple
                  • linked queue to hold nodes while they are waiting on
                  • conditions. They are then transferred to the queue to
                  • re-acquire. And because conditions can only be exclusive,
                  • we save a field by using special value to indicate shared
                  • mode.
                    /
                    Node nextWaiter;

                    /
                    *
                  • Returns true if node is waiting in shared mode.
                    /
                    final boolean isShared() {
                    return nextWaiter == SHARED;
                    }

                    /
                    *
                  • Returns previous node, or throws NullPointerException if null.
                  • Use when predecessor cannot be null. The null check could
                  • be elided, but is present to help the VM.
                  • @return the predecessor of this node
                    /
                    final Node predecessor() throws NullPointerException {
                    Node p = prev;
                    if (p == null)
                    throw new NullPointerException();
                    else
                    return p;
                    }

                    Node() { // Used to establish initial head or SHARED marker
                    }

                    Node(Thread thread, Node mode) { // Used by addWaiter
                    this.nextWaiter = mode;
                    this.thread = thread;
                    }

                    Node(Thread thread, int waitStatus) { // Used by Condition
                    this.waitStatus = waitStatus;
                    this.thread = thread;
                    }
                    }

                    /
                    *
                • Head of the wait queue, lazily initialized. Except for
                • initialization, it is modified only via method setHead. Note:
                • If head exists, its waitStatus is guaranteed not to be
                • CANCELLED.
                  /
                  private transient volatile Node head;

                  /
                  *
                • Tail of the wait queue, lazily initialized. Modified only via
                • method enq to add new wait node.
                  /
                  private transient volatile Node tail;

                  /
                  *
                • The synchronization state.
                  /
                  private volatile int state;

                  /
                  *
                • Returns the current value of synchronization state.
                • This operation has memory semantics of a {@code volatile} read.
                • @return current state value
                  /
                  protected final int getState() {
                  return state;
                  }

                  /
                  *
                • Sets the value of synchronization state.
                • This operation has memory semantics of a {@code volatile} write.
                • @param newState the new state value
                  /
                  protected final void setState(int newState) {
                  state = newState;
                  }

                  /
                  *
                • Atomically sets synchronization state to the given updated
                • value if the current state value equals the expected value.
                • This operation has memory semantics of a {@code volatile} read
                • and write.
                • @param expect the expected value
                • @param update the new value
                • @return {@code true} if successful. False return indicates that the actual
                •     value was not equal to the expected value.
                  
                /
                protected final boolean compareAndSetState(int expect, int update) {
                // See below for intrinsics setup to support this
                return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
                }

                // Queuing utilities

                /
                *
                • The number of nanoseconds for which it is faster to spin
                • rather than to use timed park. A rough estimate suffices
                • to improve responsiveness with very short timeouts.
                  /
                  static final long spinForTimeoutThreshold = 1000L;

                  /
                  *
                • Inserts node into queue, initializing if necessary. See picture above.
                • @param node the node to insert
                • @return node’s predecessor
                  /
                  private Node enq(final Node node) {
                  for (;😉 {
                  Node t = tail;
                  if (t == null) { // Must initialize
                  if (compareAndSetHead(new Node()))
                  tail = head;
                  } else {
                  node.prev = t;
                  if (compareAndSetTail(t, node)) {
                  t.next = node;
                  return t;
                  }
                  }
                  }
                  }

                  /
                  *
                • Creates and enqueues node for current thread and given mode.
                • @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
                • @return the new node
                  /
                  private Node addWaiter(Node mode) {
                  Node node = new Node(Thread.currentThread(), mode);
                  // Try the fast path of enq; backup to full enq on failure
                  Node pred = tail;
                  if (pred != null) {
                  node.prev = pred;
                  if (compareAndSetTail(pred, node)) {
                  pred.next = node;
                  return node;
                  }
                  }
                  enq(node);
                  return node;
                  }

                  /
                  *
                • Sets head of queue to be node, thus dequeuing. Called only by
                • acquire methods. Also nulls out unused fields for sake of GC
                • and to suppress unnecessary signals and traversals.
                • @param node the node
                  /
                  private void setHead(Node node) {
                  head = node;
                  node.thread = null;
                  node.prev = null;
                  }

                  /
                  *
                • Wakes up node’s successor, if one exists.
                • @param node the node
                  /
                  private void unparkSuccessor(Node node) {
                  /
                  • If status is negative (i.e., possibly needing signal) try
                  • to clear in anticipation of signalling. It is OK if this
                  • fails or if status is changed by waiting thread.
                    /
                    int ws = node.waitStatus;
                    if (ws < 0)
                    compareAndSetWaitStatus(node, ws, 0);

                    /
                  • Thread to unpark is held in successor, which is normally
                  • just the next node. But if cancelled or apparently null,
                  • traverse backwards from tail to find the actual
                  • non-cancelled successor.
                    /
                    Node s = node.next;
                    if (s == null || s.waitStatus > 0) {
                    s = null;
                    for (Node t = tail; t != null && t != node; t = t.prev)
                    if (t.waitStatus <= 0)
                    s = t;
                    }
                    if (s != null)
                    LockSupport.unpark(s.thread);
                    }

                    /
                    *
                • Release action for shared mode – signals successor and ensures
                • propagation. (Note: For exclusive mode, release just amounts
                • to calling unparkSuccessor of head if it needs signal.)
                  /
                  private void doReleaseShared() {
                  /
                  • Ensure that a release propagates, even if there are other
                  • in-progress acquires/releases. This proceeds in the usual
                  • way of trying to unparkSuccessor of head if it needs
                  • signal. But if it does not, status is set to PROPAGATE to
                  • ensure that upon release, propagation continues.
                  • Additionally, we must loop in case a new node is added
                  • while we are doing this. Also, unlike other uses of
                  • unparkSuccessor, we need to know if CAS to reset status
                  • fails, if so rechecking.
                    /
                    for (;😉 {
                    Node h = head;
                    if (h != null && h != tail) {
                    int ws = h.waitStatus;
                    if (ws == Node.SIGNAL) {
                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                    continue; // loop to recheck cases
                    unparkSuccessor(h);
                    }
                    else if (ws == 0 &&
                    !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                    continue; // loop on failed CAS
                    }
                    if (h == head) // loop if head changed
                    break;
                    }
                    }

                    /
                    *
                • Sets head of queue, and checks if successor may be waiting
                • in shared mode, if so propagating if either propagate > 0 or
                • PROPAGATE status was set.
                • @param node the node
                • @param propagate the return value from a tryAcquireShared
                  /
                  private void setHeadAndPropagate(Node node, int propagate) {
                  Node h = head; // Record old head for check below
                  setHead(node);
                  /
                  • Try to signal next queued node if:
                  • Propagation was indicated by caller,
                  • or was recorded (as h.waitStatus either before
                    
                  • or after setHead) by a previous operation
                    
                  • (note: this uses sign-check of waitStatus because
                    
                  •  PROPAGATE status may transition to SIGNAL.)
                    
                  • and
                  • The next node is waiting in shared mode,
                  • or we don't know, because it appears null
                    
                  • The conservatism in both of these checks may cause
                  • unnecessary wake-ups, but only when there are multiple
                  • racing acquires/releases, so most need signals now or soon
                  • anyway.
                    /
                    if (propagate > 0 || h == null || h.waitStatus < 0 ||
                    (h = head) == null || h.waitStatus < 0) {
                    Node s = node.next;
                    if (s == null || s.isShared())
                    doReleaseShared();
                    }
                    }

                    // Utilities for various versions of acquire

                    /
                    *
                • Cancels an ongoing attempt to acquire.
                • @param node the node
                  /
                  private void cancelAcquire(Node node) {
                  // Ignore if node doesn’t exist
                  if (node == null)
                  return;

                  node.thread = null;

                  // Skip cancelled predecessors
                  Node pred = node.prev;
                  while (pred.waitStatus > 0)
                  node.prev = pred = pred.prev;

                  // predNext is the apparent node to unsplice. CASes below will
                  // fail if not, in which case, we lost race vs another cancel
                  // or signal, so no further action is necessary.
                  Node predNext = pred.next;

                  // Can use unconditional write instead of CAS here.
                  // After this atomic step, other Nodes can skip past us.
                  // Before, we are free of interference from other threads.
                  node.waitStatus = Node.CANCELLED;

                  // If we are the tail, remove ourselves.
                  if (node == tail && compareAndSetTail(node, pred)) {
                  compareAndSetNext(pred, predNext, null);
                  } else {
                  // If successor needs signal, try to set pred’s next-link
                  // so it will get one. Otherwise wake it up to propagate.
                  int ws;
                  if (pred != head &&
                  ((ws = pred.waitStatus) == Node.SIGNAL ||
                  (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
                  pred.thread != null) {
                  Node next = node.next;
                  if (next != null && next.waitStatus <= 0)
                  compareAndSetNext(pred, predNext, next);
                  } else {
                  unparkSuccessor(node);
                  }

                  node.next = node; // help GC
                  }
                  }

                  /
                  *
                • Checks and updates status for a node that failed to acquire.
                • Returns true if thread should block. This is the main signal
                • control in all acquire loops. Requires that pred == node.prev.
                • @param pred node’s predecessor holding status
                • @param node the node
                • @return {@code true} if thread should block
                  /
                  private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
                  int ws = pred.waitStatus;
                  if (ws == Node.SIGNAL)
                  /

                  * This node has already set status asking a release
                  * to signal it, so it can safely park.
                  /
                  return true;
                  if (ws > 0) {
                  /

                  * Predecessor was cancelled. Skip over predecessors and
                  * indicate retry.
                  /
                  do {
                  node.prev = pred = pred.prev;
                  } while (pred.waitStatus > 0);
                  pred.next = node;
                  } else {
                  /

                  * waitStatus must be 0 or PROPAGATE. Indicate that we
                  * need a signal, but don’t park yet. Caller will need to
                  * retry to make sure it cannot acquire before parking.
                  /
                  compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
                  }
                  return false;
                  }

                  /
                  *
                • Convenience method to interrupt current thread.
                  /
                  static void selfInterrupt() {
                  Thread.currentThread().interrupt();
                  }

                  /
                  *
                • Convenience method to park and then check if interrupted
                • @return {@code true} if interrupted
                  /
                  private final boolean parkAndCheckInterrupt() {
                  LockSupport.park(this);
                  return Thread.interrupted();
                  }

                  /
                • Various flavors of acquire, varying in exclusive/shared and
                • control modes. Each is mostly the same, but annoyingly
                • different. Only a little bit of factoring is possible due to
                • interactions of exception mechanics (including ensuring that we
                • cancel if tryAcquire throws exception) and other control, at
                • least not without hurting performance too much.
                  /

                  /
                  *
                • Acquires in exclusive uninterruptible mode for thread already in
                • queue. Used by condition wait methods as well as acquire.
                • @param node the node
                • @param arg the acquire argument
                • @return {@code true} if interrupted while waiting
                  /
                  final boolean acquireQueued(final Node node, int arg) {
                  boolean failed = true;
                  try {
                  boolean interrupted = false;
                  for (;😉 {
                  final Node p = node.predecessor();
                  if (p == head && tryAcquire(arg)) {
                  setHead(node);
                  p.next = null; // help GC
                  failed = false;
                  return interrupted;
                  }
                  if (shouldParkAfterFailedAcquire(p, node) &&
                  parkAndCheckInterrupt())
                  interrupted = true;
                  }
                  } finally {
                  if (failed)
                  cancelAcquire(node);
                  }
                  }

                  /
                  *
                • Acquires in exclusive interruptible mode.
                • @param arg the acquire argument
                  /
                  private void doAcquireInterruptibly(int arg)
                  throws InterruptedException {
                  final Node node = addWaiter(Node.EXCLUSIVE);
                  boolean failed = true;
                  try {
                  for (;😉 {
                  final Node p = node.predecessor();
                  if (p == head && tryAcquire(arg)) {
                  setHead(node);
                  p.next = null; // help GC
                  failed = false;
                  return;
                  }
                  if (shouldParkAfterFailedAcquire(p, node) &&
                  parkAndCheckInterrupt())
                  throw new InterruptedException();
                  }
                  } finally {
                  if (failed)
                  cancelAcquire(node);
                  }
                  }

                  /
                  *
                • Acquires in exclusive timed mode.
                • @param arg the acquire argument
                • @param nanosTimeout max wait time
                • @return {@code true} if acquired
                  /
                  private boolean doAcquireNanos(int arg, long nanosTimeout)
                  throws InterruptedException {
                  if (nanosTimeout <= 0L)
                  return false;
                  final long deadline = System.nanoTime() + nanosTimeout;
                  final Node node = addWaiter(Node.EXCLUSIVE);
                  boolean failed = true;
                  try {
                  for (;😉 {
                  final Node p = node.predecessor();
                  if (p == head && tryAcquire(arg)) {
                  setHead(node);
                  p.next = null; // help GC
                  failed = false;
                  return true;
                  }
                  nanosTimeout = deadline - System.nanoTime();
                  if (nanosTimeout <= 0L)
                  return false;
                  if (shouldParkAfterFailedAcquire(p, node) &&
                  nanosTimeout > spinForTimeoutThreshold)
                  LockSupport.parkNanos(this, nanosTimeout);
                  if (Thread.interrupted())
                  throw new InterruptedException();
                  }
                  } finally {
                  if (failed)
                  cancelAcquire(node);
                  }
                  }

                  /
                  *
                • Acquires in shared uninterruptible mode.
                • @param arg the acquire argument
                  /
                  private void doAcquireShared(int arg) {
                  final Node node = addWaiter(Node.SHARED);
                  boolean failed = true;
                  try {
                  boolean interrupted = false;
                  for (;😉 {
                  final Node p = node.predecessor();
                  if (p == head) {
                  int r = tryAcquireShared(arg);
                  if (r >= 0) {
                  setHeadAndPropagate(node, r);
                  p.next = null; // help GC
                  if (interrupted)
                  selfInterrupt();
                  failed = false;
                  return;
                  }
                  }
                  if (shouldParkAfterFailedAcquire(p, node) &&
                  parkAndCheckInterrupt())
                  interrupted = true;
                  }
                  } finally {
                  if (failed)
                  cancelAcquire(node);
                  }
                  }

                  /
                  *
                • Acquires in shared interruptible mode.
                • @param arg the acquire argument
                  /
                  private void doAcquireSharedInterruptibly(int arg)
                  throws InterruptedException {
                  final Node node = addWaiter(Node.SHARED);
                  boolean failed = true;
                  try {
                  for (;😉 {
                  final Node p = node.predecessor();
                  if (p == head) {
                  int r = tryAcquireShared(arg);
                  if (r >= 0) {
                  setHeadAndPropagate(node, r);
                  p.next = null; // help GC
                  failed = false;
                  return;
                  }
                  }
                  if (shouldParkAfterFailedAcquire(p, node) &&
                  parkAndCheckInterrupt())
                  throw new InterruptedException();
                  }
                  } finally {
                  if (failed)
                  cancelAcquire(node);
                  }
                  }

                  /
                  *
                • Acquires in shared timed mode.
                • @param arg the acquire argument
                • @param nanosTimeout max wait time
                • @return {@code true} if acquired
                  /
                  private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
                  throws InterruptedException {
                  if (nanosTimeout <= 0L)
                  return false;
                  final long deadline = System.nanoTime() + nanosTimeout;
                  final Node node = addWaiter(Node.SHARED);
                  boolean failed = true;
                  try {
                  for (;😉 {
                  final Node p = node.predecessor();
                  if (p == head) {
                  int r = tryAcquireShared(arg);
                  if (r >= 0) {
                  setHeadAndPropagate(node, r);
                  p.next = null; // help GC
                  failed = false;
                  return true;
                  }
                  }
                  nanosTimeout = deadline - System.nanoTime();
                  if (nanosTimeout <= 0L)
                  return false;
                  if (shouldParkAfterFailedAcquire(p, node) &&
                  nanosTimeout > spinForTimeoutThreshold)
                  LockSupport.parkNanos(this, nanosTimeout);
                  if (Thread.interrupted())
                  throw new InterruptedException();
                  }
                  } finally {
                  if (failed)
                  cancelAcquire(node);
                  }
                  }

                  // Main exported methods

                  /
                  *
                • Attempts to acquire in exclusive mode. This method should query
                • if the state of the object permits it to be acquired in the
                • exclusive mode, and if so to acquire it.
                • This method is always invoked by the thread performing

                • acquire. If this method reports failure, the acquire method
                • may queue the thread, if it is not already queued, until it is
                • signalled by a release from some other thread. This can be used
                • to implement method {@link Lock#tryLock()}.
                • The default

                • implementation throws {@link UnsupportedOperationException}.
                • @param arg the acquire argument. This value is always the one
                •    passed to an acquire method, or is the value saved on entry
                  
                •    to a condition wait.  The value is otherwise uninterpreted
                  
                •    and can represent anything you like.
                  
                • @return {@code true} if successful. Upon success, this object has
                •     been acquired.
                  
                • @throws IllegalMonitorStateException if acquiring would place this
                •     synchronizer in an illegal state. This exception must be
                  
                •     thrown in a consistent fashion for synchronization to work
                  
                •     correctly.
                  
                • @throws UnsupportedOperationException if exclusive mode is not supported
                  /
                  protected boolean tryAcquire(int arg) {
                  throw new UnsupportedOperationException();
                  }

                  /
                  *
                • Attempts to set the state to reflect a release in exclusive
                • mode.
                • This method is always invoked by the thread performing release.

                • The default implementation throws

                • {@link UnsupportedOperationException}.
                • @param arg the release argument. This value is always the one
                •    passed to a release method, or the current state value upon
                  
                •    entry to a condition wait.  The value is otherwise
                  
                •    uninterpreted and can represent anything you like.
                  
                • @return {@code true} if this object is now in a fully released
                •     state, so that any waiting threads may attempt to acquire;
                  
                •     and {@code false} otherwise.
                  
                • @throws IllegalMonitorStateException if releasing would place this
                •     synchronizer in an illegal state. This exception must be
                  
                •     thrown in a consistent fashion for synchronization to work
                  
                •     correctly.
                  
                • @throws UnsupportedOperationException if exclusive mode is not supported
                  /
                  protected boolean tryRelease(int arg) {
                  throw new UnsupportedOperationException();
                  }

                  /
                  *
                • Attempts to acquire in shared mode. This method should query if
                • the state of the object permits it to be acquired in the shared
                • mode, and if so to acquire it.
                • This method is always invoked by the thread performing

                • acquire. If this method reports failure, the acquire method
                • may queue the thread, if it is not already queued, until it is
                • signalled by a release from some other thread.
                • The default implementation throws {@link

                • UnsupportedOperationException}.
                • @param arg the acquire argument. This value is always the one
                •    passed to an acquire method, or is the value saved on entry
                  
                •    to a condition wait.  The value is otherwise uninterpreted
                  
                •    and can represent anything you like.
                  
                • @return a negative value on failure; zero if acquisition in shared
                •     mode succeeded but no subsequent shared-mode acquire can
                  
                •     succeed; and a positive value if acquisition in shared
                  
                •     mode succeeded and subsequent shared-mode acquires might
                  
                •     also succeed, in which case a subsequent waiting thread
                  
                •     must check availability. (Support for three different
                  
                •     return values enables this method to be used in contexts
                  
                •     where acquires only sometimes act exclusively.)  Upon
                  
                •     success, this object has been acquired.
                  
                • @throws IllegalMonitorStateException if acquiring would place this
                •     synchronizer in an illegal state. This exception must be
                  
                •     thrown in a consistent fashion for synchronization to work
                  
                •     correctly.
                  
                • @throws UnsupportedOperationException if shared mode is not supported
                  /
                  protected int tryAcquireShared(int arg) {
                  throw new UnsupportedOperationException();
                  }

                  /
                  *
                • Attempts to set the state to reflect a release in shared mode.
                • This method is always invoked by the thread performing release.

                • The default implementation throws

                • {@link UnsupportedOperationException}.
                • @param arg the release argument. This value is always the one
                •    passed to a release method, or the current state value upon
                  
                •    entry to a condition wait.  The value is otherwise
                  
                •    uninterpreted and can represent anything you like.
                  
                • @return {@code true} if this release of shared mode may permit a
                •     waiting acquire (shared or exclusive) to succeed; and
                  
                •     {@code false} otherwise
                  
                • @throws IllegalMonitorStateException if releasing would place this
                •     synchronizer in an illegal state. This exception must be
                  
                •     thrown in a consistent fashion for synchronization to work
                  
                •     correctly.
                  
                • @throws UnsupportedOperationException if shared mode is not supported
                  /
                  protected boolean tryReleaseShared(int arg) {
                  throw new UnsupportedOperationException();
                  }

                  /
                  *
                • Returns {@code true} if synchronization is held exclusively with
                • respect to the current (calling) thread. This method is invoked
                • upon each call to a non-waiting {@link ConditionObject} method.
                • (Waiting methods instead invoke {@link #release}.)
                • The default implementation throws {@link

                • UnsupportedOperationException}. This method is invoked
                • internally only within {@link ConditionObject} methods, so need
                • not be defined if conditions are not used.
                • @return {@code true} if synchronization is held exclusively;
                •     {@code false} otherwise
                  
                • @throws UnsupportedOperationException if conditions are not supported
                  /
                  protected boolean isHeldExclusively() {
                  throw new UnsupportedOperationException();
                  }

                  /
                  *
                • Acquires in exclusive mode, ignoring interrupts. Implemented
                • by invoking at least once {@link #tryAcquire},
                • returning on success. Otherwise the thread is queued, possibly
                • repeatedly blocking and unblocking, invoking {@link
                • #tryAcquire} until success. This method can be used
                • to implement method {@link Lock#lock}.
                • @param arg the acquire argument. This value is conveyed to
                •    {@link #tryAcquire} but is otherwise uninterpreted and
                  
                •    can represent anything you like.
                  
                /
                public final void acquire(int arg) {
                if (!tryAcquire(arg) &&
                acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
                selfInterrupt();
                }

                /
                *
                • Acquires in exclusive mode, aborting if interrupted.
                • Implemented by first checking interrupt status, then invoking
                • at least once {@link #tryAcquire}, returning on
                • success. Otherwise the thread is queued, possibly repeatedly
                • blocking and unblocking, invoking {@link #tryAcquire}
                • until success or the thread is interrupted. This method can be
                • used to implement method {@link Lock#lockInterruptibly}.
                • @param arg the acquire argument. This value is conveyed to
                •    {@link #tryAcquire} but is otherwise uninterpreted and
                  
                •    can represent anything you like.
                  
                • @throws InterruptedException if the current thread is interrupted
                  /
                  public final void acquireInterruptibly(int arg)
                  throws InterruptedException {
                  if (Thread.interrupted())
                  throw new InterruptedException();
                  if (!tryAcquire(arg))
                  doAcquireInterruptibly(arg);
                  }

                  /
                  *
                • Attempts to acquire in exclusive mode, aborting if interrupted,
                • and failing if the given timeout elapses. Implemented by first
                • checking interrupt status, then invoking at least once {@link
                • #tryAcquire}, returning on success. Otherwise, the thread is
                • queued, possibly repeatedly blocking and unblocking, invoking
                • {@link #tryAcquire} until success or the thread is interrupted
                • or the timeout elapses. This method can be used to implement
                • method {@link Lock#tryLock(long, TimeUnit)}.
                • @param arg the acquire argument. This value is conveyed to
                •    {@link #tryAcquire} but is otherwise uninterpreted and
                  
                •    can represent anything you like.
                  
                • @param nanosTimeout the maximum number of nanoseconds to wait
                • @return {@code true} if acquired; {@code false} if timed out
                • @throws InterruptedException if the current thread is interrupted
                  /
                  public final boolean tryAcquireNanos(int arg, long nanosTimeout)
                  throws InterruptedException {
                  if (Thread.interrupted())
                  throw new InterruptedException();
                  return tryAcquire(arg) ||
                  doAcquireNanos(arg, nanosTimeout);
                  }

                  /
                  *
                • Releases in exclusive mode. Implemented by unblocking one or
                • more threads if {@link #tryRelease} returns true.
                • This method can be used to implement method {@link Lock#unlock}.
                • @param arg the release argument. This value is conveyed to
                •    {@link #tryRelease} but is otherwise uninterpreted and
                  
                •    can represent anything you like.
                  
                • @return the value returned from {@link #tryRelease}
                  /
                  public final boolean release(int arg) {
                  if (tryRelease(arg)) {
                  Node h = head;
                  if (h != null && h.waitStatus != 0)
                  unparkSuccessor(h);
                  return true;
                  }
                  return false;
                  }

                  /
                  *
                • Acquires in shared mode, ignoring interrupts. Implemented by
                • first invoking at least once {@link #tryAcquireShared},
                • returning on success. Otherwise the thread is queued, possibly
                • repeatedly blocking and unblocking, invoking {@link
                • #tryAcquireShared} until success.
                • @param arg the acquire argument. This value is conveyed to
                •    {@link #tryAcquireShared} but is otherwise uninterpreted
                  
                •    and can represent anything you like.
                  
                /
                public final void acquireShared(int arg) {
                if (tryAcquireShared(arg) < 0)
                doAcquireShared(arg);
                }

                /
                *
                • Acquires in shared mode, aborting if interrupted. Implemented
                • by first checking interrupt status, then invoking at least once
                • {@link #tryAcquireShared}, returning on success. Otherwise the
                • thread is queued, possibly repeatedly blocking and unblocking,
                • invoking {@link #tryAcquireShared} until success or the thread
                • is interrupted.
                • @param arg the acquire argument.
                • This value is conveyed to {@link #tryAcquireShared} but is
                • otherwise uninterpreted and can represent anything
                • you like.
                • @throws InterruptedException if the current thread is interrupted
                  /
                  public final void acquireSharedInterruptibly(int arg)
                  throws InterruptedException {
                  if (Thread.interrupted())
                  throw new InterruptedException();
                  if (tryAcquireShared(arg) < 0)
                  doAcquireSharedInterruptibly(arg);
                  }

                  /
                  *
                • Attempts to acquire in shared mode, aborting if interrupted, and
                • failing if the given timeout elapses. Implemented by first
                • checking interrupt status, then invoking at least once {@link
                • #tryAcquireShared}, returning on success. Otherwise, the
                • thread is queued, possibly repeatedly blocking and unblocking,
                • invoking {@link #tryAcquireShared} until success or the thread
                • is interrupted or the timeout elapses.
                • @param arg the acquire argument. This value is conveyed to
                •    {@link #tryAcquireShared} but is otherwise uninterpreted
                  
                •    and can represent anything you like.
                  
                • @param nanosTimeout the maximum number of nanoseconds to wait
                • @return {@code true} if acquired; {@code false} if timed out
                • @throws InterruptedException if the current thread is interrupted
                  /
                  public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
                  throws InterruptedException {
                  if (Thread.interrupted())
                  throw new InterruptedException();
                  return tryAcquireShared(arg) >= 0 ||
                  doAcquireSharedNanos(arg, nanosTimeout);
                  }

                  /
                  *
                • Releases in shared mode. Implemented by unblocking one or more
                • threads if {@link #tryReleaseShared} returns true.
                • @param arg the release argument. This value is conveyed to
                •    {@link #tryReleaseShared} but is otherwise uninterpreted
                  
                •    and can represent anything you like.
                  
                • @return the value returned from {@link #tryReleaseShared}
                  /
                  public final boolean releaseShared(int arg) {
                  if (tryReleaseShared(arg)) {
                  doReleaseShared();
                  return true;
                  }
                  return false;
                  }

                  // Queue inspection methods

                  /
                  *
                • Queries whether any threads are waiting to acquire. Note that
                • because cancellations due to interrupts and timeouts may occur
                • at any time, a {@code true} return does not guarantee that any
                • other thread will ever acquire.
                • In this implementation, this operation returns in

                • constant time.
                • @return {@code true} if there may be other threads waiting to acquire
                  /
                  public final boolean hasQueuedThreads() {
                  return head != tail;
                  }

                  /
                  *
                • Queries whether any threads have ever contended to acquire this
                • synchronizer; that is if an acquire method has ever blocked.
                • In this implementation, this operation returns in

                • constant time.
                • @return {@code true} if there has ever been contention
                  /
                  public final boolean hasContended() {
                  return head != null;
                  }

                  /
                  *
                • Returns the first (longest-waiting) thread in the queue, or
                • {@code null} if no threads are currently queued.
                • In this implementation, this operation normally returns in

                • constant time, but may iterate upon contention if other threads are
                • concurrently modifying the queue.
                • @return the first (longest-waiting) thread in the queue, or
                •     {@code null} if no threads are currently queued
                  
                /
                public final Thread getFirstQueuedThread() {
                // handle only fast path, else relay
                return (head == tail) ? null : fullGetFirstQueuedThread();
                }

                /
                *
                • Version of getFirstQueuedThread called when fastpath fails
                  /
                  private Thread fullGetFirstQueuedThread() {
                  /
                  • The first node is normally head.next. Try to get its
                  • thread field, ensuring consistent reads: If thread
                  • field is nulled out or s.prev is no longer head, then
                  • some other thread(s) concurrently performed setHead in
                  • between some of our reads. We try this twice before
                  • resorting to traversal.
                    /
                    Node h, s;
                    Thread st;
                    if (((h = head) != null && (s = h.next) != null &&
                    s.prev == head && (st = s.thread) != null) ||
                    ((h = head) != null && (s = h.next) != null &&
                    s.prev == head && (st = s.thread) != null))
                    return st;

                    /
                  • Head’s next field might not have been set yet, or may have
                  • been unset after setHead. So we must check to see if tail
                  • is actually first node. If not, we continue on, safely
                  • traversing from tail back to head to find first,
                  • guaranteeing termination.
                    /

                    Node t = tail;
                    Thread firstThread = null;
                    while (t != null && t != head) {
                    Thread tt = t.thread;
                    if (tt != null)
                    firstThread = tt;
                    t = t.prev;
                    }
                    return firstThread;
                    }

                    /
                    *
                • Returns true if the given thread is currently queued.
                • This implementation traverses the queue to determine

                • presence of the given thread.
                • @param thread the thread
                • @return {@code true} if the given thread is on the queue
                • @throws NullPointerException if the thread is null
                  /
                  public final boolean isQueued(Thread thread) {
                  if (thread == null)
                  throw new NullPointerException();
                  for (Node p = tail; p != null; p = p.prev)
                  if (p.thread == thread)
                  return true;
                  return false;
                  }

                  /
                  *
                • Returns {@code true} if the apparent first queued thread, if one
                • exists, is waiting in exclusive mode. If this method returns
                • {@code true}, and the current thread is attempting to acquire in
                • shared mode (that is, this method is invoked from {@link
                • #tryAcquireShared}) then it is guaranteed that the current thread
                • is not the first queued thread. Used only as a heuristic in
                • ReentrantReadWriteLock.
                  /
                  final boolean apparentlyFirstQueuedIsExclusive() {
                  Node h, s;
                  return (h = head) != null &&
                  (s = h.next) != null &&
                  !s.isShared() &&
                  s.thread != null;
                  }

                  /
                  *
                • Queries whether any threads have been waiting to acquire longer
                • than the current thread.
                • An invocation of this method is equivalent to (but may be

                • more efficient than):
                •  {@code
                  
                • getFirstQueuedThread() != Thread.currentThread() &&
                • hasQueuedThreads()}
                • Note that because cancellations due to interrupts and

                • timeouts may occur at any time, a {@code true} return does not
                • guarantee that some other thread will acquire before the current
                • thread. Likewise, it is possible for another thread to win a
                • race to enqueue after this method has returned {@code false},
                • due to the queue being empty.
                • This method is designed to be used by a fair synchronizer to

                • avoid barging.
                • Such a synchronizer’s {@link #tryAcquire} method should return
                • {@code false}, and its {@link #tryAcquireShared} method should
                • return a negative value, if this method returns {@code true}
                • (unless this is a reentrant acquire). For example, the {@code
                • tryAcquire} method for a fair, reentrant, exclusive mode
                • synchronizer might look like this:
                •  {@code
                  
                • protected boolean tryAcquire(int arg) {
                • if (isHeldExclusively()) {
                • // A reentrant acquire; increment hold count
                  
                • return true;
                  
                • } else if (hasQueuedPredecessors()) {
                • return false;
                  
                • } else {
                • // try to acquire normally
                  
                • }
                • }}
                • @return {@code true} if there is a queued thread preceding the
                •     current thread, and {@code false} if the current thread
                  
                •     is at the head of the queue or the queue is empty
                  
                • @since 1.7
                  /
                  public final boolean hasQueuedPredecessors() {
                  // The correctness of this depends on head being initialized
                  // before tail and on head.next being accurate if the current
                  // thread is first in queue.
                  Node t = tail; // Read fields in reverse initialization order
                  Node h = head;
                  Node s;
                  return h != t &&
                  ((s = h.next) == null || s.thread != Thread.currentThread());
                  }


                  // Instrumentation and monitoring methods

                  /
                  *
                • Returns an estimate of the number of threads waiting to
                • acquire. The value is only an estimate because the number of
                • threads may change dynamically while this method traverses
                • internal data structures. This method is designed for use in
                • monitoring system state, not for synchronization
                • control.
                • @return the estimated number of threads waiting to acquire
                  /
                  public final int getQueueLength() {
                  int n = 0;
                  for (Node p = tail; p != null; p = p.prev) {
                  if (p.thread != null)
                  ++n;
                  }
                  return n;
                  }

                  /
                  *
                • Returns a collection containing threads that may be waiting to
                • acquire. Because the actual set of threads may change
                • dynamically while constructing this result, the returned
                • collection is only a best-effort estimate. The elements of the
                • returned collection are in no particular order. This method is
                • designed to facilitate construction of subclasses that provide
                • more extensive monitoring facilities.
                • @return the collection of threads
                  /
                  public final Collection getQueuedThreads() {
                  ArrayList list = new ArrayList();
                  for (Node p = tail; p != null; p = p.prev) {
                  Thread t = p.thread;
                  if (t != null)
                  list.add(t);
                  }
                  return list;
                  }

                  /
                  *
                • Returns a collection containing threads that may be waiting to
                • acquire in exclusive mode. This has the same properties
                • as {@link #getQueuedThreads} except that it only returns
                • those threads waiting due to an exclusive acquire.
                • @return the collection of threads
                  /
                  public final Collection getExclusiveQueuedThreads() {
                  ArrayList list = new ArrayList();
                  for (Node p = tail; p != null; p = p.prev) {
                  if (!p.isShared()) {
                  Thread t = p.thread;
                  if (t != null)
                  list.add(t);
                  }
                  }
                  return list;
                  }

                  /
                  *
                • Returns a collection containing threads that may be waiting to
                • acquire in shared mode. This has the same properties
                • as {@link #getQueuedThreads} except that it only returns
                • those threads waiting due to a shared acquire.
                • @return the collection of threads
                  /
                  public final Collection getSharedQueuedThreads() {
                  ArrayList list = new ArrayList();
                  for (Node p = tail; p != null; p = p.prev) {
                  if (p.isShared()) {
                  Thread t = p.thread;
                  if (t != null)
                  list.add(t);
                  }
                  }
                  return list;
                  }

                  /
                  *
                • Returns a string identifying this synchronizer, as well as its state.
                • The state, in brackets, includes the String {@code “State =”}
                • followed by the current value of {@link #getState}, and either
                • {@code “nonempty”} or {@code “empty”} depending on whether the
                • queue is empty.
                • @return a string identifying this synchronizer, as well as its state
                  /
                  public String toString() {
                  int s = getState();
                  String q = hasQueuedThreads() ? “non” : “”;
                  return super.toString() +
                  "[State = " + s + ", " + q + “empty queue]”;
                  }


                  // Internal support methods for Conditions

                  /
                  *
                • Returns true if a node, always one that was initially placed on
                • a condition queue, is now waiting to reacquire on sync queue.
                • @param node the node
                • @return true if is reacquiring
                  /
                  final boolean isOnSyncQueue(Node node) {
                  if (node.waitStatus == Node.CONDITION || node.prev == null)
                  return false;
                  if (node.next != null) // If has successor, it must be on queue
                  return true;
                  /
                  • node.prev can be non-null, but not yet on queue because
                  • the CAS to place it on queue can fail. So we have to
                  • traverse from tail to make sure it actually made it. It
                  • will always be near the tail in calls to this method, and
                  • unless the CAS failed (which is unlikely), it will be
                  • there, so we hardly ever traverse much.
                    /
                    return findNodeFromTail(node);
                    }

                    /
                    *
                • Returns true if node is on sync queue by searching backwards from tail.
                • Called only when needed by isOnSyncQueue.
                • @return true if present
                  /
                  private boolean findNodeFromTail(Node node) {
                  Node t = tail;
                  for (;😉 {
                  if (t == node)
                  return true;
                  if (t == null)
                  return false;
                  t = t.prev;
                  }
                  }

                  /
                  *
                • Transfers a node from a condition queue onto sync queue.
                • Returns true if successful.
                • @param node the node
                • @return true if successfully transferred (else the node was
                • cancelled before signal)
                  /
                  final boolean transferForSignal(Node node) {
                  /
                  • If cannot change waitStatus, the node has been cancelled.
                    /
                    if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
                    return false;

                    /
                  • Splice onto queue and try to set waitStatus of predecessor to
                  • indicate that thread is (probably) waiting. If cancelled or
                  • attempt to set waitStatus fails, wake up to resync (in which
                  • case the waitStatus can be transiently and harmlessly wrong).
                    /
                    Node p = enq(node);
                    int ws = p.waitStatus;
                    if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
                    LockSupport.unpark(node.thread);
                    return true;
                    }

                    /
                    *
                • Transfers node, if necessary, to sync queue after a cancelled wait.
                • Returns true if thread was cancelled before being signalled.
                • @param node the node
                • @return true if cancelled before the node was signalled
                  /
                  final boolean transferAfterCancelledWait(Node node) {
                  if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
                  enq(node);
                  return true;
                  }
                  /
                  • If we lost out to a signal(), then we can’t proceed
                  • until it finishes its enq(). Cancelling during an
                  • incomplete transfer is both rare and transient, so just
                  • spin.
                    /
                    while (!isOnSyncQueue(node))
                    Thread.yield();
                    return false;
                    }

                    /
                    *
                • Invokes release with current state value; returns saved state.
                • Cancels node and throws exception on failure.
                • @param node the condition node for this wait
                • @return previous sync state
                  /
                  final int fullyRelease(Node node) {
                  boolean failed = true;
                  try {
                  int savedState = getState();
                  if (release(savedState)) {
                  failed = false;
                  return savedState;
                  } else {
                  throw new IllegalMonitorStateException();
                  }
                  } finally {
                  if (failed)
                  node.waitStatus = Node.CANCELLED;
                  }
                  }

                  // Instrumentation methods for conditions

                  /
                  *
                • Queries whether the given ConditionObject
                • uses this synchronizer as its lock.
                • @param condition the condition
                • @return {@code true} if owned
                • @throws NullPointerException if the condition is null
                  /
                  public final boolean owns(ConditionObject condition) {
                  return condition.isOwnedBy(this);
                  }

                  /
                  *
                • Queries whether any threads are waiting on the given condition
                • associated with this synchronizer. Note that because timeouts
                • and interrupts may occur at any time, a {@code true} return
                • does not guarantee that a future {@code signal} will awaken
                • any threads. This method is designed primarily for use in
                • monitoring of the system state.
                • @param condition the condition
                • @return {@code true} if there are any waiting threads
                • @throws IllegalMonitorStateException if exclusive synchronization
                •     is not held
                  
                • @throws IllegalArgumentException if the given condition is
                •     not associated with this synchronizer
                  
                • @throws NullPointerException if the condition is null
                  /
                  public final boolean hasWaiters(ConditionObject condition) {
                  if (!owns(condition))
                  throw new IllegalArgumentException(“Not owner”);
                  return condition.hasWaiters();
                  }

                  /
                  *
                • Returns an estimate of the number of threads waiting on the
                • given condition associated with this synchronizer. Note that
                • because timeouts and interrupts may occur at any time, the
                • estimate serves only as an upper bound on the actual number of
                • waiters. This method is designed for use in monitoring of the
                • system state, not for synchronization control.
                • @param condition the condition
                • @return the estimated number of waiting threads
                • @throws IllegalMonitorStateException if exclusive synchronization
                •     is not held
                  
                • @throws IllegalArgumentException if the given condition is
                •     not associated with this synchronizer
                  
                • @throws NullPointerException if the condition is null
                  /
                  public final int getWaitQueueLength(ConditionObject condition) {
                  if (!owns(condition))
                  throw new IllegalArgumentException(“Not owner”);
                  return condition.getWaitQueueLength();
                  }

                  /
                  *
                • Returns a collection containing those threads that may be
                • waiting on the given condition associated with this
                • synchronizer. Because the actual set of threads may change
                • dynamically while constructing this result, the returned
                • collection is only a best-effort estimate. The elements of the
                • returned collection are in no particular order.
                • @param condition the condition
                • @return the collection of threads
                • @throws IllegalMonitorStateException if exclusive synchronization
                •     is not held
                  
                • @throws IllegalArgumentException if the given condition is
                •     not associated with this synchronizer
                  
                • @throws NullPointerException if the condition is null
                  /
                  public final Collection getWaitingThreads(ConditionObject condition) {
                  if (!owns(condition))
                  throw new IllegalArgumentException(“Not owner”);
                  return condition.getWaitingThreads();
                  }

                  /
                  *
                • Condition implementation for a {@link
                • AbstractQueuedSynchronizer} serving as the basis of a {@link
                • Lock} implementation.
                • Method documentation for this class describes mechanics,

                • not behavioral specifications from the point of view of Lock
                • and Condition users. Exported versions of this class will in
                • general need to be accompanied by documentation describing
                • condition semantics that rely on those of the associated
                • {@code AbstractQueuedSynchronizer}.
                • This class is Serializable, but all fields are transient,

                • so deserialized conditions have no waiters.
                  /
                  public class ConditionObject implements Condition, java.io.Serializable {
                  private static final long serialVersionUID = 1173984872572414699L;
                  /
                  * First node of condition queue. /
                  private transient Node firstWaiter;
                  /
                  * Last node of condition queue. /
                  private transient Node lastWaiter;

                  /
                  *
                  • Creates a new {@code ConditionObject} instance.
                    /
                    public ConditionObject() { }

                    // Internal methods

                    /
                    *
                  • Adds a new waiter to wait queue.
                  • @return its new wait node
                    /
                    private Node addConditionWaiter() {
                    Node t = lastWaiter;
                    // If lastWaiter is cancelled, clean out.
                    if (t != null && t.waitStatus != Node.CONDITION) {
                    unlinkCancelledWaiters();
                    t = lastWaiter;
                    }
                    Node node = new Node(Thread.currentThread(), Node.CONDITION);
                    if (t == null)
                    firstWaiter = node;
                    else
                    t.nextWaiter = node;
                    lastWaiter = node;
                    return node;
                    }

                    /
                    *
                  • Removes and transfers nodes until hit non-cancelled one or
                  • null. Split out from signal in part to encourage compilers
                  • to inline the case of no waiters.
                  • @param first (non-null) the first node on condition queue
                    /
                    private void doSignal(Node first) {
                    do {
                    if ( (firstWaiter = first.nextWaiter) == null)
                    lastWaiter = null;
                    first.nextWaiter = null;
                    } while (!transferForSignal(first) &&
                    (first = firstWaiter) != null);
                    }

                    /
                    *
                  • Removes and transfers all nodes.
                  • @param first (non-null) the first node on condition queue
                    /
                    private void doSignalAll(Node first) {
                    lastWaiter = firstWaiter = null;
                    do {
                    Node next = first.nextWaiter;
                    first.nextWaiter = null;
                    transferForSignal(first);
                    first = next;
                    } while (first != null);
                    }

                    /
                    *
                  • Unlinks cancelled waiter nodes from condition queue.
                  • Called only while holding lock. This is called when
                  • cancellation occurred during condition wait, and upon
                  • insertion of a new waiter when lastWaiter is seen to have
                  • been cancelled. This method is needed to avoid garbage
                  • retention in the absence of signals. So even though it may
                  • require a full traversal, it comes into play only when
                  • timeouts or cancellations occur in the absence of
                  • signals. It traverses all nodes rather than stopping at a
                  • particular target to unlink all pointers to garbage nodes
                  • without requiring many re-traversals during cancellation
                  • storms.
                    /
                    private void unlinkCancelledWaiters() {
                    Node t = firstWaiter;
                    Node trail = null;
                    while (t != null) {
                    Node next = t.nextWaiter;
                    if (t.waitStatus != Node.CONDITION) {
                    t.nextWaiter = null;
                    if (trail == null)
                    firstWaiter = next;
                    else
                    trail.nextWaiter = next;
                    if (next == null)
                    lastWaiter = trail;
                    }
                    else
                    trail = t;
                    t = next;
                    }
                    }

                    // public methods

                    /
                    *
                  • Moves the longest-waiting thread, if one exists, from the
                  • wait queue for this condition to the wait queue for the
                  • owning lock.
                  • @throws IllegalMonitorStateException if {@link #isHeldExclusively}
                  •     returns {@code false}
                    
                  /
                  public final void signal() {
                  if (!isHeldExclusively())
                  throw new IllegalMonitorStateException();
                  Node first = firstWaiter;
                  if (first != null)
                  doSignal(first);
                  }

                  /
                  *
                  • Moves all threads from the wait queue for this condition to
                  • the wait queue for the owning lock.
                  • @throws IllegalMonitorStateException if {@link #isHeldExclusively}
                  •     returns {@code false}
                    
                  /
                  public final void signalAll() {
                  if (!isHeldExclusively())
                  throw new IllegalMonitorStateException();
                  Node first = firstWaiter;
                  if (first != null)
                  doSignalAll(first);
                  }

                  /
                  *
                  • Implements uninterruptible condition wait.
                    1. Save lock state returned by {@link #getState}.
                    2. Invoke {@link #release} with saved state as argument,
                    3.  throwing IllegalMonitorStateException if it fails.
                      
                    4. Block until signalled.
                    5. Reacquire by invoking specialized version of
                    6.  {@link #acquire} with saved state as argument.
                      
                    /
                    public final void awaitUninterruptibly() {
                    Node node = addConditionWaiter();
                    int savedState = fullyRelease(node);
                    boolean interrupted = false;
                    while (!isOnSyncQueue(node)) {
                    LockSupport.park(this);
                    if (Thread.interrupted())
                    interrupted = true;
                    }
                    if (acquireQueued(node, savedState) || interrupted)
                    selfInterrupt();
                    }

                    /
                    • For interruptible waits, we need to track whether to throw
                    • InterruptedException, if interrupted while blocked on
                    • condition, versus reinterrupt current thread, if
                    • interrupted while blocked waiting to re-acquire.
                      /

                      /
                      * Mode meaning to reinterrupt on exit from wait /
                      private static final int REINTERRUPT = 1;
                      /
                      * Mode meaning to throw InterruptedException on exit from wait /
                      private static final int THROW_IE = -1;

                      /
                      *
                    • Checks for interrupt, returning THROW_IE if interrupted
                    • before signalled, REINTERRUPT if after signalled, or
                    • 0 if not interrupted.
                      /
                      private int checkInterruptWhileWaiting(Node node) {
                      return Thread.interrupted() ?
                      (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
                      0;
                      }

                      /
                      *
                    • Throws InterruptedException, reinterrupts current thread, or
                    • does nothing, depending on mode.
                      /
                      private void reportInterruptAfterWait(int interruptMode)
                      throws InterruptedException {
                      if (interruptMode == THROW_IE)
                      throw new InterruptedException();
                      else if (interruptMode == REINTERRUPT)
                      selfInterrupt();
                      }

                      /
                      *
                    • Implements interruptible condition wait.
                      1. If current thread is interrupted, throw InterruptedException.
                      2. Save lock state returned by {@link #getState}.
                      3. Invoke {@link #release} with saved state as argument,
                      4.  throwing IllegalMonitorStateException if it fails.
                        
                      5. Block until signalled or interrupted.
                      6. Reacquire by invoking specialized version of
                      7.  {@link #acquire} with saved state as argument.
                        
                      8. If interrupted while blocked in step 4, throw InterruptedException.
                      /
                      public final void await() throws InterruptedException {
                      if (Thread.interrupted())
                      throw new InterruptedException();
                      Node node = addConditionWaiter();
                      int savedState = fullyRelease(node);
                      int interruptMode = 0;
                      while (!isOnSyncQueue(node)) {
                      LockSupport.park(this);
                      if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                      break;
                      }
                      if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                      interruptMode = REINTERRUPT;
                      if (node.nextWaiter != null) // clean up if cancelled
                      unlinkCancelledWaiters();
                      if (interruptMode != 0)
                      reportInterruptAfterWait(interruptMode);
                      }

                      /
                      *
                      • Implements timed condition wait.
                        1. If current thread is interrupted, throw InterruptedException.
                        2. Save lock state returned by {@link #getState}.
                        3. Invoke {@link #release} with saved state as argument,
                        4.  throwing IllegalMonitorStateException if it fails.
                          
                        5. Block until signalled, interrupted, or timed out.
                        6. Reacquire by invoking specialized version of
                        7.  {@link #acquire} with saved state as argument.
                          
                        8. If interrupted while blocked in step 4, throw InterruptedException.
                        /
                        public final long awaitNanos(long nanosTimeout)
                        throws InterruptedException {
                        if (Thread.interrupted())
                        throw new InterruptedException();
                        Node node = addConditionWaiter();
                        int savedState = fullyRelease(node);
                        final long deadline = System.nanoTime() + nanosTimeout;
                        int interruptMode = 0;
                        while (!isOnSyncQueue(node)) {
                        if (nanosTimeout <= 0L) {
                        transferAfterCancelledWait(node);
                        break;
                        }
                        if (nanosTimeout >= spinForTimeoutThreshold)
                        LockSupport.parkNanos(this, nanosTimeout);
                        if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                        break;
                        nanosTimeout = deadline - System.nanoTime();
                        }
                        if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                        interruptMode = REINTERRUPT;
                        if (node.nextWaiter != null)
                        unlinkCancelledWaiters();
                        if (interruptMode != 0)
                        reportInterruptAfterWait(interruptMode);
                        return deadline - System.nanoTime();
                        }

                        /
                        *
                        • Implements absolute timed condition wait.
                          1. If current thread is interrupted, throw InterruptedException.
                          2. Save lock state returned by {@link #getState}.
                          3. Invoke {@link #release} with saved state as argument,
                          4.  throwing IllegalMonitorStateException if it fails.
                            
                          5. Block until signalled, interrupted, or timed out.
                          6. Reacquire by invoking specialized version of
                          7.  {@link #acquire} with saved state as argument.
                            
                          8. If interrupted while blocked in step 4, throw InterruptedException.
                          9. If timed out while blocked in step 4, return false, else true.
                          /
                          public final boolean awaitUntil(Date deadline)
                          throws InterruptedException {
                          long abstime = deadline.getTime();
                          if (Thread.interrupted())
                          throw new InterruptedException();
                          Node node = addConditionWaiter();
                          int savedState = fullyRelease(node);
                          boolean timedout = false;
                          int interruptMode = 0;
                          while (!isOnSyncQueue(node)) {
                          if (System.currentTimeMillis() > abstime) {
                          timedout = transferAfterCancelledWait(node);
                          break;
                          }
                          LockSupport.parkUntil(this, abstime);
                          if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                          break;
                          }
                          if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                          interruptMode = REINTERRUPT;
                          if (node.nextWaiter != null)
                          unlinkCancelledWaiters();
                          if (interruptMode != 0)
                          reportInterruptAfterWait(interruptMode);
                          return !timedout;
                          }

                          /
                          *
                          • Implements timed condition wait.
                            1. If current thread is interrupted, throw InterruptedException.
                            2. Save lock state returned by {@link #getState}.
                            3. Invoke {@link #release} with saved state as argument,
                            4.  throwing IllegalMonitorStateException if it fails.
                              
                            5. Block until signalled, interrupted, or timed out.
                            6. Reacquire by invoking specialized version of
                            7.  {@link #acquire} with saved state as argument.
                              
                            8. If interrupted while blocked in step 4, throw InterruptedException.
                            9. If timed out while blocked in step 4, return false, else true.
                            /
                            public final boolean await(long time, TimeUnit unit)
                            throws InterruptedException {
                            long nanosTimeout = unit.toNanos(time);
                            if (Thread.interrupted())
                            throw new InterruptedException();
                            Node node = addConditionWaiter();
                            int savedState = fullyRelease(node);
                            final long deadline = System.nanoTime() + nanosTimeout;
                            boolean timedout = false;
                            int interruptMode = 0;
                            while (!isOnSyncQueue(node)) {
                            if (nanosTimeout <= 0L) {
                            timedout = transferAfterCancelledWait(node);
                            break;
                            }
                            if (nanosTimeout >= spinForTimeoutThreshold)
                            LockSupport.parkNanos(this, nanosTimeout);
                            if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                            break;
                            nanosTimeout = deadline - System.nanoTime();
                            }
                            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                            interruptMode = REINTERRUPT;
                            if (node.nextWaiter != null)
                            unlinkCancelledWaiters();
                            if (interruptMode != 0)
                            reportInterruptAfterWait(interruptMode);
                            return !timedout;
                            }

                            // support for instrumentation

                            /
                            *
                            • Returns true if this condition was created by the given
                            • synchronization object.
                            • @return {@code true} if owned
                              /
                              final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
                              return sync == AbstractQueuedSynchronizer.this;
                              }

                              /
                              *
                            • Queries whether any threads are waiting on this condition.
                            • Implements {@link AbstractQueuedSynchronizer#hasWaiters(ConditionObject)}.
                            • @return {@code true} if there are any waiting threads
                            • @throws IllegalMonitorStateException if {@link #isHeldExclusively}
                            •     returns {@code false}
                              
                            /
                            protected final boolean hasWaiters() {
                            if (!isHeldExclusively())
                            throw new IllegalMonitorStateException();
                            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                            if (w.waitStatus == Node.CONDITION)
                            return true;
                            }
                            return false;
                            }

                            /
                            *
                            • Returns an estimate of the number of threads waiting on
                            • this condition.
                            • Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength(ConditionObject)}.
                            • @return the estimated number of waiting threads
                            • @throws IllegalMonitorStateException if {@link #isHeldExclusively}
                            •     returns {@code false}
                              
                            /
                            protected final int getWaitQueueLength() {
                            if (!isHeldExclusively())
                            throw new IllegalMonitorStateException();
                            int n = 0;
                            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                            if (w.waitStatus == Node.CONDITION)
                            ++n;
                            }
                            return n;
                            }

                            /
                            *
                            • Returns a collection containing those threads that may be
                            • waiting on this Condition.
                            • Implements {@link AbstractQueuedSynchronizer#getWaitingThreads(ConditionObject)}.
                            • @return the collection of threads
                            • @throws IllegalMonitorStateException if {@link #isHeldExclusively}
                            •     returns {@code false}
                              
                            /
                            protected final Collection getWaitingThreads() {
                            if (!isHeldExclusively())
                            throw new IllegalMonitorStateException();
                            ArrayList list = new ArrayList();
                            for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                            if (w.waitStatus == Node.CONDITION) {
                            Thread t = w.thread;
                            if (t != null)
                            list.add(t);
                            }
                            }
                            return list;
                            }
                            }

                            /
                            *
                          • Setup to support compareAndSet. We need to natively implement
                          • this here: For the sake of permitting future enhancements, we
                          • cannot explicitly subclass AtomicInteger, which would be
                          • efficient and useful otherwise. So, as the lesser of evils, we
                          • natively implement using hotspot intrinsics API. And while we
                          • are at it, we do the same for other CASable fields (which could
                          • otherwise be done with atomic field updaters).
                            /
                            private static final Unsafe unsafe = Unsafe.getUnsafe();
                            private static final long stateOffset;
                            private static final long headOffset;
                            private static final long tailOffset;
                            private static final long waitStatusOffset;
                            private static final long nextOffset;

                            static {
                            try {
                            stateOffset = unsafe.objectFieldOffset
                            (AbstractQueuedSynchronizer.class.getDeclaredField(“state”));
                            headOffset = unsafe.objectFieldOffset
                            (AbstractQueuedSynchronizer.class.getDeclaredField(“head”));
                            tailOffset = unsafe.objectFieldOffset
                            (AbstractQueuedSynchronizer.class.getDeclaredField(“tail”));
                            waitStatusOffset = unsafe.objectFieldOffset
                            (Node.class.getDeclaredField(“waitStatus”));
                            nextOffset = unsafe.objectFieldOffset
                            (Node.class.getDeclaredField(“next”));

                            } catch (Exception ex) { throw new Error(ex); }
                            }

                            /
                            *
                          • CAS head field. Used only by enq.
                            /
                            private final boolean compareAndSetHead(Node update) {
                            return unsafe.compareAndSwapObject(this, headOffset, null, update);
                            }

                            /
                            *
                          • CAS tail field. Used only by enq.
                            /
                            private final boolean compareAndSetTail(Node expect, Node update) {
                            return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
                            }

                            /
                            *
                          • CAS waitStatus field of a node.
                            /
                            private static final boolean compareAndSetWaitStatus(Node node, int expect,int update) {
                            return unsafe.compareAndSwapInt(node, waitStatusOffset, expect, update);
                            }

                            /
                            *
                          • CAS next field of a node.
                            */
                            private static final boolean compareAndSetNext(Node node,Node expect,Node update) {
                            return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
                            }
                            }

                            再看看Node是什么?看到这里的同学,是不是有种热泪盈眶的感觉,这尼玛,不就是 双向链表么?
                        • 最后我们可以发现锁的存储结构就两个东西:“双向链表” + “int类型状态”。需要注意的是,他们的变量都被" transient和volatile修饰。

                          看上面的代码

                          /**
                           * Sync object for non-fair locks
                           */
                          static final class NonfairSync extends Sync {
                              private static final long serialVersionUID = 7316153563782823691L;
                              /**
                               * Performs lock.  Try immediate barge, backing up to normal
                               * acquire on failure.
                               */
                              final void lock() {
                          

                          //AQS中的int类型的state值,这里就是通过CAS(乐观锁)去修改state的值。 lock的基本操作还是通过乐观锁来实现的
                          if (compareAndSetState(0, 1))
                          setExclusiveOwnerThread(Thread.currentThread());
                          else
                          acquire(1);
                          }
                          protected final boolean tryAcquire(int acquires) {
                          return nonfairTryAcquire(acquires);
                          }
                          }
                          下面我们来看一下CAS compareAndSetState(0, 1)方法是如何来获取锁的,

                          protected final boolean compareAndSetState(int expect, int update) {
                          // See below for intrinsics setup to support this
                          return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
                          }
                          那么没有获取到锁,等待获取锁是如何实现的?我们可以看一下else分支的逻辑,acquire方法:

                          public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
                          public final void acquire(int arg) {
                          if (!tryAcquire(arg) &&
                          acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
                          selfInterrupt();
                          }
                          }
                          这里干了三件事情:

                          tryAcquire:会尝试再次通过CAS获取一次锁。

                          addWaiter:将当前线程加入上面锁的双向链表(等待队列)中

                          acquireQueued:通过自旋,判断当前队列节点是否可以获取锁。

                          public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
                          //tryAcquire 方法
                          protected boolean tryAcquire(int arg) {
                          throw new UnsupportedOperationException();
                          }

                          //addWaiter 方法
                          /**
                          * Creates and enqueues node for current thread and given mode.
                          *
                          * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
                          * @return the new node
                          */
                          private Node addWaiter(Node mode) {
                          Node node = new Node(Thread.currentThread(), mode);
                          // Try the fast path of enq; backup to full enq on failure
                          Node pred = tail;
                          if (pred != null) {
                          node.prev = pred;
                          if (compareAndSetTail(pred, node)) {
                          pred.next = node;
                          return node;
                          }
                          }
                          enq(node);
                          return node;
                          }

                          // acquireQueued 方法
                          /**
                          * Acquires in exclusive uninterruptible mode for thread already in
                          * queue. Used by condition wait methods as well as acquire.
                          *
                          * @param node the node
                          * @param arg the acquire argument
                          * @return {@code true} if interrupted while waiting
                          */
                          final boolean acquireQueued(final Node node, int arg) {
                          boolean failed = true;
                          try {
                          boolean interrupted = false;
                          for (;😉 {
                          final Node p = node.predecessor();
                          if (p == head && tryAcquire(arg)) {
                          setHead(node);
                          p.next = null; // help GC
                          failed = false;
                          return interrupted;
                          }
                          if (shouldParkAfterFailedAcquire(p, node) &&
                          parkAndCheckInterrupt())
                          interrupted = true;
                          }
                          } finally {
                          if (failed)
                          cancelAcquire(node);
                          }
                          }

                        评论
                        添加红包

                        请填写红包祝福语或标题

                        红包个数最小为10个

                        红包金额最低5元

                        当前余额3.43前往充值 >
                        需支付:10.00
                        成就一亿技术人!
                        领取后你会自动成为博主和红包主的粉丝 规则
                        hope_wisdom
                        发出的红包
                        实付
                        使用余额支付
                        点击重新获取
                        扫码支付
                        钱包余额 0

                        抵扣说明:

                        1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
                        2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

                        余额充值