Java & AQS & 源码

前言


 相关系列

 涉及内容

源码


/*
 * 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 juc.locks;

import juc.CountDownLatch;
import juc.TimeUnit;
import sun.misc.Unsafe;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Queue;

/**
 * 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.
 * 提供一个实现阻塞锁和依赖先入先出等待队列的颔联同步器(信号量,事件等)的框架。该类被设计用于作为绝大部分依
 * 赖一个单一原子int值来代表状态的同步器的基础。子类必须定义改变状态的受保护方法,并且定义就当前对象的状态获取
 * 和释放而言的意义是什么。指定这些,类中的其它方法都将基于排队和阻塞机制执行。子类可以维持其它状态字段,但只
 * 能使用getState(),setState()和compareAndSetState方法操作的原子更新int值被同步追踪。
 * <p>
 * Subclasses should be defined as non-public internal helper classes that are used to implement the synchronization
 * properties of their enclosing class.  Class {@code AbstractQueuedSynchronizer} does not implement any
 * synchronization interface.  Instead it defines methods such as {@link #acquireInterruptibly} that can be invoked as
 * appropriate by concrete locks and related synchronizers to implement their public methods.
 * 子类应该被定义为非公共的内部帮助类以用于实现他们外围类的同步属性。抽象队列同步器类不实现任何同步接口,反而
 * 定义方法例如acquireInterruptibly()可以通过具体的锁和关联同步器被调用以实现他们的公共方法。
 * <p>
 * This class supports either or both a default <em>exclusive</em> mode and a <em>shared</em> mode. When acquired
 * in exclusive mode, attempted acquires by other threads cannot succeed. Shared mode acquires by multiple threads
 * may (but need not) succeed. This class does not &quot;understand&quot; these differences except in the mechanical
 * sense that when a shared mode acquire succeeds, the next waiting thread (if one exists) must also determine whether
 * it can acquire as well. Threads waiting in the different modes share the same FIFO queue. Usually, implementation
 * subclasses support only one of these modes, but both can come into play for example in a {@link ReadWriteLock}.
 * Subclasses that support only exclusive or only shared modes need not define the methods supporting the unused mode.
 * 该类支持任意一个默认独占模式和一个共享模式的一个或两个。当在独占模式中获取时,通过其它线程尝试获取将不会成
 * 功。共享模式通过多线程获取可能(但不一定)成功。该类不理解这些不同,除非在在机械意义上,当一个共享模式获取
 * 成功时,下个等待的线程(如果存在)也必须确定它是否也可以获取。线程在不同模式中等待共享相同的先入先出队列。
 * 通常,实现子类只支持一种模式,但可以在例如读写锁中都发挥作用。只支持独占/共享模式的子类不需要定义方法支持
 * 使用的模式。
 * <p>
 * This class defines a nested {@link ConditionObject} class that can be used as a {@link Condition} implementation by
 * subclasses supporting exclusive mode for which method {@link #isHeldExclusively} reports whether synchronization
 * is exclusively held with respect to the current thread, method {@link #release} invoked with the current
 * {@link #getState} value fully releases this object, and {@link #acquire}, given this saved state value, eventually
 * restores this object to its previous acquired state.  No {@code AbstractQueuedSynchronizer} method otherwise
 * creates such a condition, so if this constraint cannot be met, do not use it.  The behavior of {@link ConditionObject}
 * depends of course on the semantics of its synchronizer implementation.
 * 这个类定义了一个嵌套的条件对象类,它可以被支持独占模式的子类用作条件接口实现。在这种【独占】模式下,
 * isHeldExclusively()方法用于报告同步是否被当前线程是否独占持有,release()方法随着getState()值被调用以完全释放当
 * 前对象【完全释放?这能完全释放?如果有重入呢?】,而acquire()给出这个保存的状态值,最终将该对象恢复到其先前
 * 获得的状态【这段话除了知道AQS自定义了条件接口的实现类外其它的完全看不懂...也不是看不懂,就是感觉乱七八糟的,
 * 不应该放在一起说】。AbstractQueuedSynchronizer方法不会创建这样的条件,所以如果不能满足此约束,就不要使用它。
 * 条件对象的行为当然取决于它的同步实现语义【完全看不懂这段什么了些什么东西】。
 * <p>
 * This class provides inspection, instrumentation, and monitoring methods for the internal queue, as well as similar
 * methods for condition objects. These can be exported as desired into classes using an
 * {@code AbstractQueuedSynchronizer} for their synchronization mechanics.
 * 该类提供内部队列的检查,仪表化及监视方法,与条件对象的方法相似。  因此可以根据需要导出一个AQS进类中作为它
 * 们的同步机制。
 * <p>
 * Serialization of this class stores only the underlying atomic integer maintaining state, so deserialized objects have
 * empty thread queues. Typical subclasses requiring serializability will define a {@code readObject} method that
 * restores this to a known initial state upon deserialization.
 * 该类的序列化仅存储维护状态的底层原子整数,所以反序列化对象有空线程队列【即序列化只保存状态值,不保存同步队
 * 列中线程】。一般子类序列化需求会定义一个在反序列化后重置已知初始状态的readObject()方法。
 * <h3>Usage</h3>
 * 用法
 * <p>
 * To use this class as the basis of a synchronizer, redefine the following methods, as applicable, by inspecting and/or
 * modifying the synchronization state using {@link #getState}, {@link #setState} and/or {@link #compareAndSetState}:
 * 为了使用该类作为同步器的基础,通过使用getState()、setState()和/或compareAndSetState()方法检查和/或修改同步状
 * 态来重定义以下的方法以令其适用:
 * <ul>
 * <li> {@link #tryAcquire} 尝试获取
 * <li> {@link #tryRelease} 尝试释放
 * <li> {@link #tryAcquireShared} 尝试获取共享
 * <li> {@link #tryReleaseShared} 尝试释放共享
 * <li> {@link #isHeldExclusively} 是否持有独占
 * </ul>
 * <p>
 * Each of these methods by default throws {@link UnsupportedOperationException}.  Implementations of these methods
 * must be internally thread-safe, and should in general be short and not block. Defining these methods is the
 * <em>only</em> supported means of using this class. All other methods are declared {@code final} because they
 * cannot be independently varied.
 * 这些方法的每个默认都通过抛出不支持操作异常实现。这些方法的实现必须内部线程安全【即相对线程安全】,并通常应
 * 该短路【即快速返回,执行时间不长】和不阻塞。定义这些方法是使用这个类唯一支持的意义【即这些方法就是为了配合
 * 该类在实际中的使用而定义的】。所有其它方法都要被声明为final【不可重写】因为它们无法独立改变【即方法之间相互
 * 依赖,重写会导致AQS无法运行】。
 * <p>
 * You may also find the inherited methods from {@link AbstractOwnableSynchronizer} useful to keep track of the
 * thread owning an exclusive synchronizer.  You are encouraged to use them -- this enables monitoring and diagnostic
 * tools to assist users in determining which threads hold locks.
 * 你也可能从AOS中找到继承的方法用于记录线程拥有的独占同步器。你被鼓励使用它们 —— 这会开启监视和诊断工具以
 * 帮助用户确定哪个线程持有锁。
 * <p>
 * Even though this class is based on an internal FIFO queue, it does not automatically enforce FIFO acquisition policies.
 * The core of exclusive synchronization takes the form:
 * 虽然该类基于内部先入先出队列【实现】,但它不会自动强制执行先入先出获取策略。独占同步的核心为采取这样的格式:
 * <pre>
 * Acquire:
 * 获取
 *     while (!tryAcquire(arg)) {
 *        <em>enqueue thread if it is not already queued</em>;
 *        如果尚未排队则排队
 *        <em>possibly block current thread</em>;
 *        当前线程可能阻塞
 *     }
 *
 * Release:
 * 释放
 *     if (tryRelease(arg))
 *        <em>unblock the first queued thread</em>;
 *        解除首个排队线程
 * </pre>
 * <p>
 * (Shared mode is similar but may involve cascading signals.)
 * (分享模式是类似的但可能牵涉连续传递的信号。)
 * <p id="barging">
 * Because checks in acquire are invoked before enqueuing, a newly acquiring thread may <em>barge</em> ahead of
 * others that are blocked and queued.  However, you can, if desired, define {@code tryAcquire} and/or
 * {@code tryAcquireShared} to disable barging by internally invoking one or more of the inspection methods, thereby
 * providing a <em>fair</em> FIFO acquisition order. In particular, most fair synchronizers can define
 * {@code tryAcquire} to return {@code false} if {@link #hasQueuedPredecessors} (a method specifically designed to
 * be used by fair synchronizers) returns {@code true}.  Other variations are possible.
 * 因为检查在acquire()方法中于排队之前被调用,所以一个新获取线程可能先于阻塞及排队的线程之前碰撞【即先于两者
 * 尝试获取状态】。此外,如果有需求,你可以定义tryAcquire()及/或tryAcquireShared()方法在内部调用一个或更多检查
 * 方法来关闭碰撞【通过检查来避免插队,任何想要获取状态的线程都需要先加入同步队列】,从而提供一个公平的先入
 * 先出获取顺序。在特定情况下,如果hasQueuedPredecessors()方法返回true(方法被具体指定设计用于公平同步器),
 * 则大部分公平同步器可以定义tryAcquire()方法返回false【hasQueuedPredecessors()方法返回true说明之前已经有线程
 * 在尝试获取状态了,因此为了保证公平性,当前线程不可以直接获取状态而是要先加入同步队列按顺序获取状态】。
 * 其它变化也有可能。
 * <p>
 * Throughput and scalability are generally highest for the default barging (also known as <em>greedy</em>,
 * <em>renouncement</em>, and <em>convoy-avoidance</em>) strategy. While this is not guaranteed to be fair or
 * starvation-free, earlier queued threads are allowed to recontend before later queued threads, and each recontention
 * has an unbiased chance to succeed against incoming threads.  Also, while acquires do not &quot;spin&quot; 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.
 * 默认碰撞策略的吞吐量和可拓展性通常是最高的(好被认为是贪婪的,可拒绝的、可回避的)。虽然这无法保证公平或无
 * 饥饿,更早的排队线程被允许在更后的排队线程前重竞争,并且每次重竞争有公正的机会超过新到来的线程。此外,虽然
 * 获取没有通常意义上的自旋,但它们在阻塞之前可能穿插着其它计算执行尝试获取的多次调用。这给出了当独占同步只被
 * 短暂持有时自旋的大部分好处,而当它不是时【短暂的独占持有】就没有这大部分的缺点【即自旋的成本大于线程等待的
 * 成本】。如果期望如此,你可以通过在随着"快速路径"检查调用获取方法之前增强它,所以如果同步器大概不会竞争时可
 * 能只做hasContended()及/或hasQueuedThreads()的预检查。
 * <p>
 * This class provides an efficient and scalable basis for synchronization in part by specializing its range of use to
 * synchronizers that can rely on {@code int} state, acquire, and release parameters, and an internal FIFO wait queue.
 * When this does not suffice, you can build synchronizers from a lower level using {@link atomic atomic} classes, your
 * own custom {@link Queue} classes, and {@link LockSupport} blocking support.
 * 该类通过指定使用范围至可以依赖int状态,获取,和释放参数,并且一个内部的陷入线程的等待队列的同步器来为同步提
 * 供一个有效及可拓展的基础。当这么做还不自已满足时,你可以使用原子类从底层构建同步去,你有用定制队列类,以及
 * LockSupport阻塞支持【即如果AQS的机制无法满足你的同步需求,你可以自我定义相关的类来实现机制】。
 * <h3>Usage Examples</h3>
 * 使用案例
 * <p>
 * Here is a non-reentrant mutual exclusion lock class that uses the value zero to represent the unlocked state, and
 * one to represent the locked state. While a non-reentrant lock does not strictly require recording of the current owner
 * thread, this class does so anyway to make usage easier to monitor. It also supports conditions and exposes one of the
 * instrumentation methods:
 * 这是一个使用零值来代表未加锁状态,以及使用一来代表加锁状态的不可重入互斥锁类。虽然不可重入锁并不严格要求记
 * 录当前所有者线程,但这个类还是这样做了,以便更容易监控使用情况。它还支持条件并公开了一种检测方法:
 *  <pre> {@code
 * class Mutex implements Lock, 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
 *     // 如果状态为0则获取锁
 *     public boolean tryAcquire(int acquires) {
 *       // Otherwise unused
 *       // 否则未使用?
 *       assert acquires == 1;
 *       // 通过CAS操作获取状态,如果成功则将当前线程设置为独占拥有者线程。
 *       if (compareAndSetState(0, 1)) {
 *         setExclusiveOwnerThread(Thread.currentThread());
 *         return true;
 *       }
 *       return false;
 *     }
 *
 *     // Releases the lock by setting state to zero
 *     // 通过设置状态0来释放锁
 *     protected boolean tryRelease(int releases) {
 *       // 否则未使用?
 *       assert releases == 1;
 *       // 判断[状态]是否为0,是则直接抛出非法监视状态异常,因为锁在非持有状态下是不允许被释放的。
 *       if (getState() == 0) throw new IllegalMonitorStateException();
 *       setExclusiveOwnerThread(null);
 *       setState(0);
 *       return true;
 *     }
 *
 *     // Provides a Condition
 *     // 提供一个条件
 *     Condition newCondition() { return new ConditionObject(); }
 *
 *     // Deserializes properly
 *     // 正确反序列化
 *     private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
 *       s.defaultReadObject();
 *       setState(0); // reset to unlocked state
 *     }
 *   }
 *
 *   // The sync object does all the hard work. We just forward to it.
 *   private final Sync sync = new Sync();
 *
 *   public void lock()                { sync.acquire(1); }
 *   public boolean tryLock()          { return sync.tryAcquire(1); }
 *   public void unlock()              { sync.release(1); }
 *   public Condition newCondition()   { return sync.newCondition(); }
 *   public boolean isLocked()         { return sync.isHeldExclusively(); }
 *   public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
 *   public void lockInterruptibly() throws InterruptedException {
 *     sync.acquireInterruptibly(1);
 *   }
 *   public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
 *     return sync.tryAcquireNanos(1, unit.toNanos(timeout));
 *   }
 * }}</pre>
 *
 * <p>
 * Here is a latch class that is like a {@link 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.
 * 这个一个类似于CountDownLatch的闭锁,除了只能获取单个信号以释放。因为一个闭锁不是独占的,所以它使用共享
 * 获取即释放方法。
 *  <pre> {@code
 * class BooleanLatch {
 *
 *   private static class Sync extends AbstractQueuedSynchronizer {
 *     boolean isSignalled() { return getState() != 0; }
 *
 *     protected int tryAcquireShared(int ignore) {
 *       return isSignalled() ? 1 : -1;
 *     }
 *
 *     protected boolean tryReleaseShared(int ignore) {
 *       setState(1);
 *       return true;
 *     }
 *   }
 *
 *   private final Sync sync = new Sync();
 *   public boolean isSignalled() { return sync.isSignalled(); }
 *   public void signal()         { sync.releaseShared(1); }
 *   public void await() throws InterruptedException {
 *     sync.acquireSharedInterruptibly(1);
 *   }
 * }}</pre>
 *
 * @author Doug Lea
 * @since 1.5
 */
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements Serializable {

    private static final long serialVersionUID = 7373984972572414691L;

    /**
     * Creates a new {@code AbstractQueuedSynchronizer} instance with initial synchronization state of zero.
     * 随着0的初始同步状态创建一个抽象队列同步器
     *
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 抽象队列同步器
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 初始化抽象可拥有同步器。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    protected AbstractQueuedSynchronizer() {
    }

    /**
     * Wait queue node class.
     * 等待队列节点类
     * <p>
     * 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.
     * 等待队列是"CLH"所队列的的变种。CLH锁通常被用于自旋锁。我们为了【实现】阻塞同步器而使用它们,但使用持有某
     * 些有关它节点的前驱节点中线程的基本信息的基本策略。一个"状态"字段在每个节点中记录是否一个线程是否应该阻塞。
     * 当节点的前驱节点被释放时它会被传递信号。队列中的每个节点都会充当一个指定通知风格的监视器,以持有单个等待
     * 线程。状态字段不控制线程是否被授予锁等。一个线程如果是队列中的首个【节点/线程】,它可能尝试获取【状态】。
     * 但不保证首个成功;它只是被授予竞争的权利。所以当前释放的竞争线程可能需要重等待。
     * <p>
     * To enqueue into a CLH lock, you atomically splice it in as new tail. To dequeue, you just set the head field.
     * 为了排队进入一个CLH锁,你需要原子地链接它进入作为新尾节点。为了出队,你只需要设置头节点字段。
     * <pre>
     *      +------+  prev +-----+       +-----+
     * head |      | <---- |     | <---- |     |  tail
     *      +------+       +-----+       +-----+
     * </pre>
     *
     * <p>
     * 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.
     * 插入一个CLH队列只需要在尾部进行一个单原子操作,所以这是从非队列至队列的的一个简单原子分界点。相似地,出
     * 队,只需要更新头节点。此外,它为节点做了更多的工作以确定谁是它的后继节点,以部分【即无法完全解决】处理
     * 由于超时和中断而可能导致的取消。
     * <p>
     * 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/
     * "前驱"链接(不在原本的CLH locks中使用)主要需要处理取消。如果一个节点被取消,它的后继节点(通常)会重链接
     * 一个未取消的后继节点。在自旋锁情况中类似机制的说明,通过在
     * Scott and Scherer http://www.cs.rochester.edu/u/scott/synchronization/查看资料。
     * <p>
     * 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.)
     * 我们还使用"后继"链接以实现阻塞机制。每个节点的线程ID被保存在它们所拥有的节点中,所以一个前驱节点会通过遍历
     * 下个链接以确定是哪个线程并通知后继节点至唤醒。后继节点的确定必须避免与新队列节点设置它们前驱节点的"后继"字
     * 段发生竞争【如果一个节点的后继节点正在发生变化,那么这个节点的后继节点是无法被确定的】。当必要时可通过在
     * 一个节点的后继节点可能为null时从原子更新"尾"节点向后检查来解决。(或者不同说,后继引用最佳化时我们通常不需
     * 要向后扫描)
     * <p>
     * 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.
     * 取消推行某些稳定性至基础算法。自我们必须为了其它节点的取消而轮询起,因此我们可能无法注意到被取消的节点是
     * 在我们前面还是后面。这通过在取消后唤醒后继节点处理,允许它们稳定一个新前驱节点,除非我们可以查明一个将携
     * 带该责任的未取消节点。
     * <p>
     * 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.
     * CLH队列需要一个哨兵头节点以开始。但是我们不会在构造时创建,因为如果从未竞争它将徒劳无功【一种极致优化的
     * 思想】。相反,该节点在首次竞争【即首个节点入队时】被构造并作为首个头/尾节点。
     * <p>
     * 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.
     * 线程在条件中等待使用相同的节点,但是使用额外的链接【即使用不同的字段保存后继节点,这意味着一个节点可以同
     * 时处于同步队列和条件队列中,虽然逻辑上是不允许的,但是节点在两种队列中相互迁移的时候确实会存在同时处于两
     * 者的中间状态】。条件值需要在简单(非并发)链接队列中链接节点,因为因为只有当独占持有时才能访问【即将节点
     * 迁移至条件队列的过程不需要院子操作,因为这本就是在线程安全的情况下执行的】。一个状态字段的指定值被用于标
     * 记节点在哪个队列中。
     * <p>
     * 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. Creates a new
     * {@code AbstractQueuedSynchronizer} instance with initial synchronization state of zero.
     * 感谢Dave Dice, Mark Moir, Victor Luchangco, Bill Scherer和Michael Scott,以及JSR-166专家组的成员,为本课程的
     * 设计提供了有用的想法,讨论和批评。创建一个新的抽象队列同步器实例初始同步状态为零。
     *
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 抽象队列同步器
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 初始化抽象可拥有同步器。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    static final class Node {

        /**
         * Marker to indicate a node is waiting in shared mode
         * 代表一个节点在共享模式中等待的标记
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 共享
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 用于持有一个不可变的节点,该节点被作为节点为共享节点的标志。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        static final Node SHARED = new Node();
        /**
         * Marker to indicate a node is waiting in exclusive mode
         * 代表一个节点在独占模式中等待的标记
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 独占
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 用于持有null,以作为节点为共享节点的标志。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        static final Node EXCLUSIVE = null;

        /**
         * waitStatus value to indicate thread has cancelled
         * 用于表示线程已被取消的等待状态值
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 取消
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 用于记录状态值1,以作为节点已被取消的标志
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        static final int CANCELLED = 1;
        /**
         * waitStatus value to indicate successor's thread needs unparking
         * 用于表示后继节点的线程需要被唤醒的等待状态值
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 信号
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 用于记录状态值-1,以作为节点的后继节点需要被唤醒的标志
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        static final int SIGNAL = -1;
        /**
         * waitStatus value to indicate thread is waiting on condition
         * 用于表示线程在条件中等待的等待状态值
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 条件
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 用于记录状态值-2,以作为节点位于条件队列中的标志
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        static final int CONDITION = -2;
        /**
         * waitStatus value to indicate the next acquireShared should unconditionally propagate
         * 用于表示下次获取共享状态应该无条件传播的等待状态值
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 传播
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 用于记录状态值-3,以作为节点需要强制唤醒后继节点线程的标志
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        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
         * 状态字段,只取值:
         * 取消(1) —— 当前节点由于超时或中断而被取消。节点永远无法脱离该状态。在这种情况下,伴随取消节点的线
         * 程永远不会再阻塞。
         * 无(0) —— 初始值,没有实际意义。
         * 信号(-1) —— 节点的后继节点是(或很快将)阻塞的(通过挂起),因此当前节点必须在它释放或取消的时候解
         * 除它后继节点的挂起。为了避免竞争,获取方法必须先表示它们需要一个信号,然后再重试原子获取,然后在失败
         * 中阻塞【即只有因为信号被唤醒或进入等待状态的线程才允许再次尝试获取状态,否则只能将自身所属节点从同步
         * 队列中退出】。
         * 条件(-2):节点当前位于条件队列中。它将无法被用作同步队列节点直至被转移,到那时其状态将被设置为0。(
         * 这里使用这个值与该字段的其他用法无关,但可以简化机制。)
         * 传播(-3):一次释放分享应该传播至其它节点。其在doReleaseShared()方法中被设置(只有头节点)以确保传播
         * 继续,即使其它操作后来干预。
         * <p>
         * 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.
         * 这些值被安排简化数字上的使用。非负值意味着一个节点不需要信号。所以,大部分代码不需要检查特殊值,只需
         * 要标记。
         * <p>
         * 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).
         * 普通同步节点该字段会被初始化为0,而条件节点则为CONDITION(-2)。其使用CAS操作进行修改(或当可能时,
         * 无条件易失性写入)
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 等待状态
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 记录当前节点的位置/状态
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        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.
         * 链接为检查等待状态所依赖的当前节点/线程的前驱节点。在排队期间分配,并只在出队后设置为null(为了GC的好
         * 处)。此外,在前驱节点取消后,我们会在【向前】寻找非取消节点期间发生短路【即遍历的距离变短】,这种情
         * 况会经常存在,因为头节点从不取消:一个节点成为头节点只作为成功获取的结果。一个取消线程永远不会再获取
         * 中成功,并且一个线程只能取消它自己,而无法取消任意其它节点。
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 前驱
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 持有当前节点的前驱节点
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        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.
         * 链接到当前节点/线程在释放后解除锁定的后继节点。在排队期间分配,在避开取消前驱节点时调整【即定位新的后
         * 继节点时调整】,在退出队列时为空(为了GC)。enq操作直到附加之后才会分配前一个节点的next字段,因此看到一
         * 个空的next字段并不一定意味着节点位于队列的末尾。但是,如果next字段显示为空,我们可以从尾部扫描prev进行
         * 双重检查。取消节点的下一个字段被设置为指向节点本身,而不是null,以使isOnSyncQueue更容易。
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 后继
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 持有当前节点的后继节点
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        volatile Node next;

        /**
         * The thread that enqueued this node.  Initialized on construction and nulled out after use.
         * 在当前节点中排队的线程。在构造时初始化并在使用后设置为null
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 线程
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 持有在当前节点中等待的线程
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        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.
         * 链接下个在条件中等待的节点,或者记录指定值SHARED。因为条件队列只有在独占模式中持有才能访问,我们只需
         * 在它们在条件中等待期间使用一个简单的链接队列来持有节点。它们会被迁移至该队列以备重获取。并且因为条件
         * 只能独占【即独占模式下访问】,我们通过使用指定值来节省一个字段来表示共享模式。
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 下个等待者
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 持有当前节点在条件队列中的后继节点,或持有SHARED节点对象表示当前节点为共享节点
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        Node nextWaiter;

        /**
         * Returns true if node is waiting in shared mode.
         * 如果节点在共享模式中等待则返回true。
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 是否共享
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 判断当前节点是否为共享节点,是则返回true;否则返回false。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法通过判断[下个等待者]是否为[共享]实现,是则返回true;否则返回false。
         */
        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.
         * 返回先前的节点,或者如果为null则返回空指针异常。当前驱节点不为空时使用。该null的检查可以省略,但存在可
         * 以帮助VM
         *
         * @return the predecessor of this node 当前节点的前驱节点
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 是否共享
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 获取当前节点的前驱节点,如果不存在则抛出空指针异常
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法首先会判断[前驱]是否为null,是则抛出空指针异常,否则返回[前驱]。
         */
        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null) {
                throw new NullPointerException();
            } else {
                return p;
            }
        }

        /**
         * Used to establish initial head or SHARED marker
         * 用于建立初始头节点或共享标记。
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 节点
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 创建节点
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        Node() {
        }

        /**
         * Used by addWaiter
         * 通过新增等待者使用
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 节点
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 创建指定线程/模式的节点
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法会将指定模式/线程分别赋值给[下个等待者]及[线程]。
         */
        Node(Thread thread, Node mode) {
            this.nextWaiter = mode;
            this.thread = thread;
        }

        /**
         * Used by Condition
         * 通过条件使用
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 节点
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 创建指定线程/等待状态的节点
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法会将指定等待状态/线程分别赋值给[等待状态]及[线程]。
         */
        Node(Thread thread, int waitStatus) {
            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.
     * 等待队列的头节点。除非初始化,否则它只通过setHead方法修改。注意:如果头节点存在,则它的等待状态不保证为
     * CANCELLED(1:取消)。
     *
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 头
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 持有当前AQS同步队列中的头节点。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    private transient volatile Node head;

    /**
     * Tail of the wait queue, lazily initialized.  Modified only via method enq to add new wait node.
     * 等待队列的尾节点,延迟初始化。只有通过enq()方法新增新等待节点修改。
     *
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 尾
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 持有当前AQS同步队列中的尾节点。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    private transient volatile Node tail;

    /**
     * The synchronization state.
     * 同步状态
     *
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 状态
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 记录当前AQS的状态
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    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 当前状态值
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 获取状态
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 获取当前AQS的状态
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法通过返回[状态]实现。
     */
    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 新状态值
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 设置状态
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 设置当前AQS的状态为指定状态
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法通过将[状态]赋值为指定状态实现。
     */
    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.
     * 如果成功则返回true。返回false表示实际值不等于期望值。
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * CAS状态
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 将当前AQS的状态通过CAS操作由指定旧值设置为指定新值,成功则返回true;否则返回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    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.
     * 使用快速自旋而非使用定时挂起的纳秒数。随着非常短的超时时间进行粗糙的提出足以增长响应性。
     *
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 超时自旋阈值
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 记录当前AQS同步队列中线程执行执行自旋操作的阈值1000ns,当线程的等待截止时间少于阈值时线程不会进入等待
     * 状态,而是会连续性的自旋。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    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 节点的寝取节点
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 插入
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 将指定节点从尾部插入当前AQS的同步队列中,并返回其前驱节点,即原本的尾节点。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法会无限循环的前提下执行以下操作,之所以要无限循环执行是因为并发可能导致下列涉及CAS操作的地方执行
     * 失败,因此需要不断尝试执行至成功为止。
     * ---- 首先其会判断[尾]是否存在,不存在则说明指定节点是首个加入同步队列的节点,因此在将之加入前需要先创建一
     * 个头/哨兵节点通过CAS操作加入同步队列中。被插入的头/哨兵节点会同时作为同步队列的[头]及[尾]。
     * ---- 头/哨兵节点插入同步队列后或其本身就已存在的情况下,方法会尝试将指定节点插入同步队列中,即令之成为新
     * 的[尾]。方法会先将的指定节点的[前驱]赋值为[尾],随后通过CAS操作将[尾]设置为指定节点,最后将旧[尾]的[后继]赋
     * 值为新[尾],即指定节点。完成这一步后意味着指定节点已被加入同步队列中,方法执行结束。
     */
    private Node enq(final Node node) {
        // ---- 方法会无限循环的前提下执行以下操作,之所以要无限循环执行是因为并发可能导致下列涉及CAS操作的地方执
        // 行失败,因此需要不断尝试执行至成功为止。
        // ---- 首先其会判断[尾]是否存在,不存在则说明指定节点是首个加入同步队列的节点,因此在将之加入前需要先创建
        // 一个头/哨兵节点通过CAS操作加入同步队列中。被插入的头/哨兵节点会同时作为同步队列的[头]及[尾]。
        // ---- 头/哨兵节点插入同步队列后或其本身就已存在的情况下,方法会尝试将指定节点插入同步队列中,即令之成为
        // 新的[尾]。方法会先将的指定节点的[前驱]赋值为[尾],随后通过CAS操作将[尾]设置为指定节点,最后将旧[尾]的[后
        // 继]赋值为新[尾],即指定节点。完成这一步后意味着指定节点已被加入同步队列中,方法执行结束。
        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 独占为Node.EXCLUSIVE,共享为Node.SHARED
     * @return the new node 新节点
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 新增等待者
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 根据当前线程及指定模式创建节点并从尾部插入当前AQS的同步队列
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会通过当前线程与指定模式创建节点,并在[尾]存在的情况下直接尝试将该节点加入同步队列中。这是一
     * 种快速路径的尝试而非完整的插入流程,因为其略去了头/哨兵节点创建的相关逻辑,直接基于[尾]已存在的情况下尝
     * 试将节点加入同步队列中。并且这种尝试通常是可以成功的,因为只要有节点加入过同步队列,则[尾]通常都是存在的,
     * 并且竞争也并非时时存在,因此CAS操作也不会失败。这种快速路径的尝试可以有效地提升性能,避免方法频繁进入无
     * 意义的循环而损耗性能。
     * ---- 只有在[尾]不存在或者快速路径尝试失败的情况下,方法才会调用enq(final Node node)方法进入完整节点插入流程。
     * 该流程除了添加了头/哨兵节点的创建逻辑外,还会在以死循环的方式执行,确保节点插入操作即使在并发竞争的情况
     * 下也一定会成功。
     */
    private Node addWaiter(Node mode) {
        // ---- 方法首先会通过当前线程与指定模式创建节点,并在[尾]存在的情况下直接尝试将该节点加入同步队列中。这
        // 是一种快速路径的尝试而非完整的插入流程,因为其略去了头/哨兵节点创建的相关逻辑,直接基于[尾]已存在的
        // 情况下尝试将节点加入同步队列中。并且这种尝试通常是可以成功的,因为只要有节点加入过同步队列,则[尾]通
        // 常都是存在的,并且竞争也并非时时存在,因此CAS操作也不会失败。这种快速路径的尝试可以有效地提升性能,
        // 避免方法频繁进入无意义的循环而损耗性能。
        // ---- 只有在[尾]不存在或者快速路径尝试失败的情况下,方法才会调用enq(final Node node)方法进入完整节点插入
        // 流程。该流程除了添加了头/哨兵节点的创建逻辑外,还会在以死循环的方式执行,确保节点插入操作即使在并发
        // 竞争的情况下也一定会成功。
        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.
     * 设置队列的头节点,一次出队。只在获取方法中调用。为了有利于GC还会将不使用的字段置null,并且阻止无必要的信
     * 号和遍历。
     *
     * @param node the node
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 设置头
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 设置当前AQS同步队列的头节点,以实现将头节点出队的作用。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法会将[头]设置为指定节点,这一步不需要的使用CAS操作保证线程安全,因为只有[头]的后继节点线程才被允许
     * 设置将自身节点设置为新[头],故而同一时间只会有一条线程进行该操作。随后方法会将指定节点的[线程]和[前驱]设置
     * 为null,因为指定节点被设置为[头]后这些数据也就没有作用了,置null有助于相关对象的GC回收,减少垃圾的遗留。
     */
    private void setHead(Node node) {
        // ---- 方法会将[头]设置为指定节点,这一步不需要的使用CAS操作保证线程安全,因为只有[头]的后继节点线程才被
        // 允许设置将自身节点设置为新[头],故而同一时间只会有一条线程进行该操作。随后方法会将指定节点的[线程]和[
        // 前驱]设置为null,因为指定节点被设置为[头]后这些数据也就没有作用了,置null有助于相关对象的GC回收,减少垃
        // 圾的遗留。
        head = node;
        node.thread = null;
        node.prev = null;
    }

    /**
     * Wakes up node's successor, if one exists.
     * 唤醒节点的后继节点,如果存在的话。
     *
     * @param node the node
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 启动后继节点
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 唤醒指定节点的真后继节点线程。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 当前方法是"取消/状态唤醒"的公用底层方法,作用是唤醒指定节点的真后继节点线程。当唤醒类型为"取消唤醒"时
     * 指定节点即为取消节点;而当唤醒类型为"状态唤醒"时指定节点即为[头节点]。
     * ---- 方法首先会判断指定节点的[等待状态]是否 < 0,即是否为SIGNAL(-1:信号)/PROPAGATE(-3:传播),是则
     * 将之CAS赋值为0,并且不在意该CAS的执行结果。这段代码根据唤醒类型与线程模式的不同其含义也是不同的。当唤
     * 醒类型为"取消唤醒"时该代码没有任何意义,因为取消节点时其[等待状态]必然为CANCELLED(1:取消);而当唤醒
     * 类型为"状态唤醒"时则还需要根据线程的模式再次进行场景。
     * ---- 当唤醒类型为"状态唤醒"时,如果线程以独占模式工作,则该代码负责将[头节点]的[等待状态]由SIGNAL(-1:信
     * 号)CAS赋值为0,即状态CAS;而如果线程以共享模式工作,则该代码负责将[头节点]的[等待状态]由SIGNAL(-1:信
     * 号)/PROPAGATE(-3:传播)发现/还原为0,即还原CAS。还原CAS本质上是一种优化行为,执行成功意味着包含设
     * 置该PROPAGATE(-3:传播)的传播共享线程在内之前所有线程释放的[状态]只要没有被并发[获取]就一定能被当前唤
     * 醒共享线程查找/唤醒的首个非空节点[线程]查询到,从而有助于首个非空节点[线程]自身更精确的判断是否继续执行"状
     * 态唤醒"而减少对PROPAGATE(-3:传播)的依赖。又因为还原CAS是优化行为,因此对于独占线程来说该行为是可以
     * "状态唤醒"的流程中移除的,因此自然也就无需在意执行的结果,而这也就导致了兼容该代码的独占线程即使状态CAS
     * 失败也可以查找/唤醒首个非空节点[线程]。
     * ---- 无论指定节点的[等待状态]是否被CAS赋值,是否CAS赋值成功,在这之后方法都会唤醒指定节点的真后继节点[线
     * 程]。方法首先会判断指定节点的[后继节点]是否存在及取消。不存在或已取消则从[尾节点]/指定节点为起/终点进行前
     * 遍历,并覆盖式记录沿途遇到的所有未取消节点,直至遍历到指定节点或无节点可节点可遍历为止。最后记录的未取消
     * 节点会被视作指定节点的真后继节点。
     * ---- 在真后继节点存在的情况下,方法会将之唤醒。
     */
    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.
         * 如果状态为负数(即可能需要发送信号),尝试清理预料到的信号。如果这失败了或者状态被等待线程【这里特指共
         * 享模式下】所改变也是允许的。
         */

        // ---- 当前方法是"取消/状态唤醒"的公用底层方法,作用是唤醒指定节点的真后继节点线程。当唤醒类型为"取消唤醒"
        // 时指定节点即为取消节点;而当唤醒类型为"状态唤醒"时指定节点即为[头节点]。
        // ---- 方法首先会判断指定节点的[等待状态]是否 < 0,即是否为SIGNAL(-1:信号)/PROPAGATE(-3:传播),是
        // 则将之CAS赋值为0,并且不在意该CAS的执行结果。这段代码根据唤醒类型与线程模式的不同其含义也是不同的。
        // 当唤醒类型为"取消唤醒"时该代码没有任何意义,因为取消节点时其[等待状态]必然为CANCELLED(1:取消);而
        // 当唤醒类型为"状态唤醒"时则还需要根据线程的模式再次进行场景。
        // ---- 当唤醒类型为"状态唤醒"时,如果线程以独占模式工作,则该代码负责将[头节点]的[等待状态]由SIGNAL(-1:信
        // 号)CAS赋值为0,即状态CAS;而如果线程以共享模式工作,则该代码负责将[头节点]的[等待状态]由SIGNAL(-1:
        // 信号)/PROPAGATE(-3:传播)发现/还原为0,即还原CAS。还原CAS本质上是一种优化行为,执行成功意味着包
        // 含设置该PROPAGATE(-3:传播)的传播共享线程在内之前所有线程释放的[状态]只要没有被并发[获取]就一定能被
        // 当前唤醒共享线程查找/唤醒的首个非空节点[线程]查询到,从而有助于首个非空节点[线程]自身更精确的判断是否继
        // 续执行"状态唤醒"而减少对PROPAGATE(-3:传播)的依赖。又因为还原CAS是优化行为,因此对于独占线程来说该
        // 行为是可以"状态唤醒"的流程中移除的,因此自然也就无需在意执行的结果,而这也就导致了兼容该代码的独占线程
        // 即使状态CAS失败也可以查找/唤醒首个非空节点[线程]。
        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.
         * 线程启动所有的后继节点,这种情况下通常只是下个节点【即[后继]中记录的节点】。但如果[后继]已被取消或明显为
         * null,则从[尾]向前遍历找到实际未取消的后继节点。
         */

        // ---- 无论指定节点的[等待状态]是否被CAS赋值,是否CAS赋值成功,在这之后方法都会唤醒指定节点的真后继节点[线
        // 程]。方法首先会判断指定节点的[后继节点]是否存在及取消。不存在或已取消则从[尾节点]/指定节点为起/终点进行
        // 前遍历,并覆盖式记录沿途遇到的所有未取消节点,直至遍历到指定节点或无节点可节点可遍历为止。最后记录的未
        // 取消节点会被视作指定节点的真后继节点。
        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.)
     * 关于共享模式的发布活动 -- 传递信号至后继节点并确定传播。(注意:关于独占模式,发布就等于调用头节点的
     * unparkSuccessor(),如果它需要传递信号。)
     *
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 释放共享
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 唤醒当前AQS同步队列共享首个非空节点线程。
     */
    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.
         * 确保释放传播,即使有其它获取/释放正在执行。如果需要传递信号,尝试对头节点执行unparkSuccessor方法(这
         * 通常以常规的方式进行)。如果不需要【传递信号】,则将状态设置为PROPAGATE(-3:传播)以确保释放后传
         * 播继续【即当前线程释放共享状态后可以保证后续线程也释放】。此外,我们必须循环以防止在我们执行该操作期
         * 间有新节点添加。还有,与unparkSuccessor()方法的其它调用不同,我们需要知道CAS重设状态是否失败,如果失
         * 败则需要重新检查。
         */

        // ---- "状态唤醒"的整体操作需要在死循环中执行,一是令共享线程在唤醒CAS失败时重试;二是避免在"状态唤醒"过
        // 程中有新节点并发入队等待导致传播中断的情况发生。
        for (; ; ) {
            // ---- "状态唤醒"首先会判断[头节点]是否存在且是否不与[尾节点]相同,否则说明当前同步队列中只有虚拟节点
            // 存在,而由于虚拟节点是空节点,因此唤醒也就谈起,方法会跳转至循环的尾部判断是否退出循环。
            Node h = head;
            if (h != null && h != tail) {
                // ---- 如果[头节点]存在且不为[尾节点],"状态唤醒"会判断[头节点]的[等待状态]是否为SIGNAL(-1:信号),
                // 是则意味着首个非空节点[线程]需要被唤醒。方法首先会将[头节点]的[等待状态]SIGNAL(-1:信号)CAS赋
                // 值改为0,该行为的作用是告知其它并发独占/共享线程首个非空节点[线程]已无需再唤醒以避免重复唤醒。
                // 为了保证这一点当该CAS失败时共享线程需要跳转至开头重新循环,而如果执行成功则当前共享线程将调用
                // unparkSuccessor(Node node)方法查找/唤醒首个非空节点[线程]。
                int ws = h.waitStatus;
                if (ws == Node.SIGNAL) {
                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) {
                        // loop to recheck cases
                        // 循环检查情况
                        continue;
                    }
                    unparkSuccessor(h);
                } else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) {
                    // ---- 如果[头节点]的[等待状态]为0,说明存在其它独占/共享在并发"状态唤醒"首个非空节点[线程]。此时
                    // 共享线程会尝试将[头节点]的[等待状态]由0CAS赋值为PROPAGATE(-3:传播),用于向被唤醒的首个非
                    // 空节点[线程] 表示有共享线程在其被唤醒及获取[状态]期间释放了[状态],作为首个非空节点[线程]用于维
                    // 护"共享节点[线程]状态唤醒的传播性"的判断条件之一。

                    // loop on failed CAS
                    // CAS失败时循环
                    continue;
                }
            }
            // ---- 在执行唤醒、传播或什么也不做后,方法最终会进入到当前的结束判断中。如果在上述操作结束后同步队列
            // 的[头节点]没有发生变化,则当前共享线程将直接退出循环,意味着整个"状态唤醒"流程正式结束;否则将会继
            // 续循环,意味着新一轮"状态唤醒"的执行。
            // ---- 同步队列的[头节点]之所以会在"状态唤醒"中变化是因为旧[头节点]已被成功获取[状态]的首个非空节点[线程]
            // 所移除,但我们并无法得知首个非空节点[线程]是否是被唤醒以及被唤醒的场景为何,因为这里的并发场景很多。
            // 之所以将[头节点]未变化作为结束"状态唤醒"的判断条件是为了防止在"状态唤醒"执行期间有新共享节点加入同步
            // 队列导致"共享节点[线程]状态唤醒的传播性"被打破。
            // ---- 当当前共享线程在完成"状态唤醒"后如果发现[头节点]发生了变化,则意味着旧[头节点]已被首个非空节点[线
            // 程]移除。首个非空节点[线程]可能是早已存在同步队列中并被"状态/取消/虚假唤醒"的,但也有可能获取[状态]失
            // 败而加入的新节点[线程]。事实上这种可能性其实更大一些,因为首个非空节点[线程]从唤醒到"前驱式清理"到获
            // 取[状态]再到移除[头节点]是一个相对漫长的过程,因此唤醒共享线程在查找/唤醒后立即发现[头节点]已变化这
            // 种情况虽然不是不可能,但概率总体上较小。而在首个非空节点[线程]为新节点[线程]且为共享模式的情况下其
            // 可能会因为无法通过[状态]的存在性判断而不继续执行"状态唤醒",从而导致"共享节点[线程]状态唤醒的传播性"被
            // 打破。因此在该情况下当前共享线程会强制性的再执行一次"状态唤醒"以维护这种情况。
            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.
     * 设置队列头,并检查后继节点是否在共享模式下等待,如果是这样,则在设置了propagate > 0或propagate状态时进
     * 行传播。
     *
     * @param node      the node 节点
     * @param propagate the return value from a tryAcquireShared 从tryAcquireShared方法中返回值
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 设置头并传播
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 唤醒当前AQS同步队列头节点的后继节点线程,并在条件允许的情况下辅助唤醒后续的后继节点
     * 线程。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    private void setHeadAndPropagate(Node node, int propagate) {
        // Record old head for check below
        // 记录旧头用于下方检查


        // ---- 方法首先会调用setHead(Node node)方法将指定节点设置为[头],将将其[线程]和[前驱]赋值为null,但[后继]会
        // 被保留,因此指定节点必然会是[头]的后继节点。在这一步之后,指定节点的后继节点线程
        // 就已经可能被唤醒了【如果满足唤醒条件的话】。因为除了当前线程之外,释放共享状态的线程也可能会被保留下
        // 来辅助后续未取消后继节点线程的唤醒。
        Node h = head;
        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.
         * 如果传播由调用者指示【即通过传入的共享状态的数量判断是否进行唤醒操作】,或者通过先前的操作被记录(例如
         * h.waitStatus在setHead之前或之后)(注意:这里使用等待状态的符号检查,因为传播状态可能会被转换为信号)
         * 【即通过设置指定节点为[头]操作前后的旧/新[头]的[等待状态]判断是否进行唤醒操作,并且这种状态使用的是范围
         * 判断,而不是等值判断,因此[等待状态]可能在这期间从传播状态转换为信号状态】,并且下个节点在共享模式中
         * 等待,或者我们不知道,因为它看起来为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 节点
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 设置头并传播
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 唤醒当前AQS同步队列头节点的后继节点线程,并在条件允许的情况下辅助唤醒后续的后继节点
     * 线程。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    private void cancelAcquire(Node node) {
        // Ignore if node doesn't exist
        // 如果节点不存在则异常


        // ---- 方法首先会判断指定节点是否存在,否则直接返回以结束方法;是则将指定节点的[线程]赋值为null,目的是断
        // 开指定节点与之线程的关联,以帮助GC。随后以指定节点为起点向前遍历寻找首个未取消前驱节点,并移除沿途遇
        // 到的所有已取消前驱节点。已取消节点的移除是指将指定节点的[前驱]赋值已取消节点的前驱节点,这样当遍历结
        // 束时,指定节点就与首个未取消前驱节点建立了关联。但也只是指定节点与首个未取消前驱节点建立了关联,因为
        // 此时首个未取消前驱节点还未将[后继]设置为指定节点。此外,被移除的已取消节点的[前驱]及[后继]不会被修改,
        // 也就是说已取消节点会以外节点/外链的形式存在,即
        // A <--> B <--> C <--> D <--> E <--> F <--> G
        // 会变为
        //                  C <--> D <--> E
        // A <--> B <----------------------------- F <--> G
        // 节点B/C的[后继]及[前驱]尾对方,而节点E的[后继]为节点F,但节点F的[前驱]为B。这么做的目的是为了防止遍历
        // 的异常中断,因为取消操作是可以并发的,也就是同一时间可能有多个执行取消操作的线程在以其各自指定节点为
        // 起点向前遍历以寻找首个未取消前驱节点。如果我们将沿途已取消节点的[前驱]及[后继]置null,则其它执行取消操
        // 作的线程的遍历就可能被异常中断,从而无法找到各自的首个未取消前驱节点。

        if (node == null) {
            return;
        }
        // ---- 断开[线程]与节点的关联。
        node.thread = null;
        // Skip cancelled predecessors
        // 跳过已取消的前驱节点。

        // ---- 在取消节点[线程]前遍历寻找真前驱节点的过程中不断将取消节点的[前驱节点]赋值为遍历节点的取消节点,直
        // 至找到真前驱节点为止。
        Node pred = node.prev;
        while (pred.waitStatus > 0) {
            node.prev = pred = pred.prev;
        }

        // ---- 当找到首个未取消前驱节点而结束遍历后,我们需要建立其与指定节点的链接,或者更严格的说是建立首个未
        // 取消前驱节点与指定节点后继节点的链接。方法首先会判断指定节点是为[尾],是则尝试通过CAS操作将首个未取
        // 消前驱节点设置为[尾],成功则再通过CAS操作将之[后继]设置为null,因为[尾]的[后继]为null。该CAS操作可能会
        // 失败,因为存在追加新节点的线程与之竞争。但我们在意该失败,因为失败了意味着首个未取消前驱节点的[后继]
        // 被赋值为新节点,也同样是正确的值,也意味着首个前驱取消节点不再是[尾]了。但需要注意的是:即使首个未取
        // 消前驱节点被成功设置为了[尾],也不会修改其[等待状态]为0,因此可以知道的是:即使是没有[后继]的[尾],其[
        // 等待状态]也不一定为0。


        // 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.
        // predNext理论上是用于断开链接的节点【如果没有并发的话】,如果不是则下方的CAS将失败,在这种情况下,我
        // 们会输掉与其它取消或信号的竞争,所以不用进一步的活动。
        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.
        // 这里可以使用无条件的写入代替CAS操作。在这一步原子操作后,其它节点可以跳过我们。之前,我们不受其他线
        // 程的干扰。
        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.
            // 如果后继节点需要传递信号,尝试设置前驱的下个链接,这样它将得到【信号】。所以它将获取一个。否则唤
            // 醒它用于传播。


            // ---- 如果指定节点不是[尾]或者通过CAS操作将首个未取消前驱节点设置为[尾]失败了,则说明指定节点不是[尾]
            // 或没有成功成为[尾]。此时方法会进行三个条件的判断,以确定首个未取消前驱节点能否与指定节点的后继节点
            // 建立链接,即将首个未取消前驱节点的[后继]赋值为指定节点的后继节点,从而做到彻底清理两个节点之前包含
            // 指定节点在内的所有取消节点的效果。这三个条件判断的内容和具体含义如下:
            // 条件一 —— 首个未取消前驱节点不为[头] —— 意味着此时首个未取消前驱节点不为[头]。该条件判断无法保证
            // 首个未取消前驱节点在后续两个条件判断过程中成为[头],但可以将已成为[头]的首个未取消前驱节点拦截下来,
            // 使之避免后续复杂的条件判断及操作,直接以唤醒其后继节点的方式完成清理,以简化整体流程并提升性能。
            // 条件二 —— 首个未取消前驱节点的[等待状态]为SIGNAL(-1:信号),或[等待状态] <= 0且成功通过CAS操作
            // 被设置为SIGNAL(-1:信号) —— 意味着首个未取消前驱节点的[等待状态]支持设置新[后继]。判断首个未取
            // 消前驱节点的[等待状态]是否支持设置新[后继]的核心在于[等待状态]是否为SIGNAL(-1:信号)或是否可以成
            // 功设置为SIGNAL(-1:信号)。因为我们需要确保链接完成后,当存在状态时,指定节点的后继节点中的[线程]
            // 是可以被唤醒的。上述[等待状态] <= 0的判断相对而言比较难以理解,此处进行一个详细的解释:首先,如果[
            // 等待状态] > 0,则说明首个未取消前驱节点已经因为并发的原因被取消了,这种状态下不应该为之设置[后继],
            // 而是应该将之一同移除;当[等待状态] == 0时,意味着首个未取消前驱节点尚未被其原后继节点【原后继节点
            // 是必然存在的,因为首个未取消前驱节点是通过前遍历得到的】将之[等待状态]赋值为SIGNAL(-1:信号)】,
            // 因此修改其[等待状态]为SIGNAL(-1:信号);[等待状态]为SIGNAL(-1:信号)没有讨论必要;而
            // CONDITION(-2:条件)是节点在条件队列中才可能出现的等待状态;而最后的PROPAGATE(-3:传播)则是
            // 非常极限的情况,理论上该等待状态只有头节点才可能被设置,而条件一/三注定了首个未取消前驱节点基本不
            // 可能是[头],但也存在一种非常微小的可能,即进行条件一判断时还不是[头],但在条件二判断时就成为[头]了,
            // 并且直到条件三判断位置,其[线程]都没有被置null,这就造成了节点[等待状态]从PROPAGATE(-3:传播)转
            // 变为SIGNAL(-1:信号)的极小可能。该情况下最大的担忧是身为[头]的首个未取消前驱节点有没有可能在其设
            // 置[后继]前/时被移除呢?而如果可能被移除,又是否会对[后继]设置过程造成影响呢?答案是可能会被移除,但
            // 不会造成影响。首先,首个未取消前驱节点不可能被其到指定节点的后继节点之前的节点线程移除,因为这期间
            // 都是取消节点,而取消节点内部是没有[线程]可用于移除头节点的,因此首个未取消前驱节点只可能被指定节点
            // 的后继节点之后的首个未取消后继节点线程移除。但如果是这样的情况,该节点线程必须要先移除两者间的所有
            // 取消节点,那也就是说,如果该节点线程真的移除了身为[头]的首个未取消前驱节点,则其也就必然移除了其与
            // 首个未取消前驱节点之间的所有【取消】节点。在这种情况下,即使当前的重设[后继]操作尚未执行或执行失败
            // 也都没有任何影响,因为这与执行成后被移除是一样的结果。
            // 条件三 —— 首个未取消前驱节点的[线程]不为空 —— 意味着首个未取消前驱节点在上述过程中没有被取消,
            // 因为将节点[等待状态]设置为CANCELLED(1:取消)要比将节点[线程]置null要后;但可能已被成为[头],因为
            // 将[头]赋值为节点要比将节点[线程]置null要前【以上情况不考虑指令重排序】。
            // ---- 这三个条件被满足说明首个未取消前驱节点可支持将[后继]赋值为指定节点的后继节点。但在正式设置之前,
            // 方法会先判断指定节点是否存在后继节点且其[等待状态]是否 <= 0,只有在满足上述条件的情况下才会尝试将
            // 首个未取消前驱节点的[后继]通过CAS操作设置为指定节点的后继节点。首先,由于之前已经判断过指定节点是
            // 否为[尾],因此此时指定节点不存在后继节点的情况应该是极少的,但也不排除后继节点被迁移至条件队列等情
            // 况。这种情况下我们似乎应该将首个未取消前驱节点的[后继]置null,但因为
            // 并且即使失败了也不会重试,因为

            // ---- 将首个未取消前驱节点的[后继]设置为指定节点的后继节点的CAS操作可能会失败,因为同一时间可能有多个
            // 节点被取消,并且这些取消节点相邻导致其首个未取消前驱节点实际上是相同的,因此最终也只有一个取消节点
            // 的后继节点可以被设置为首个未取消前驱节点的[后继]。最关键的是方法无法保证[后继]为这些相邻取消节点的
            // 最后一个的后继节点,即使next.waitStatus <= 0判断可以提高这个概率,但依然存在并发情况可以突破这个限
            // 制。例如当前线程执行完next.waitStatus <= 0的判断后,当前节点的后继节点线程就被取消并同样执行到了该
            // 位置,从而突破了next.waitStatus <= 0的防护造成两个相邻取消节点竞争同一个未取消前驱节点[后继]的局面,
            // 而最后可能是当前指定节点获得成功。CAS失败后并不会继续尝试,因为只要有一个取消节点的后继节点被设置
            // [后继]成功,其它取消节点就失去意义了。
            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);
            }
            // help GC
            // 帮助GC

            // ---- 上述流程全部执行完毕后,会将指定节点的[后继]设置为自身,从而起到断开后继引用的作用,并有助于GC。
            // 为什么不直接置null呢?这是因为指定节点可能会被其它线程持有,而如果这些线程发现指定节点的[后继]为null,
            // 会认为指定节点是[尾],因此不可以置null。而对于源码中其它将节点[后继]置null的情况,是因为其保证了它不会
            // 被其它线程持有,或不会访问节点的[后继],例如从头部移除[头]。
            // ---- 可以发现的是,虽然指定节点的[后继]会被自引用,但方法并没有对其[前驱]进行修改,甚至没有将指定节点
            // 的后继节点的[前驱]赋值为首个未取消前驱节点。这就意味着即使指定节点的后继节点被成功设置为了首个未取消
            // 前驱节点的[后继],其对首个未取消前驱节点也不是直接引用,而是通过指定节点建立的间接引用,即:
            // 首个未取消前驱节点 --> 指定节点的后继节点
            // 首个未取消前驱节点 <-- 指定节点 <-- 指定节点的后继节点
            // 由此也可知, 指定节点的后继节点是否被设置为首个未取消前驱节点的[后继],其都会被保留在同步队列中,目
            // 的与上文所述相同,即避免的中断其它线程的前遍历。因此,一个标准的取消节点其[前驱]为其的首个未取消前
            // 驱节点,而[后继]则为自引用。这个可能会影响后遍历,例如在调用unparkSuccessor(Node node)方法唤醒指定节
            // 点的后继节点时如果发现其[后继]为取消节点时是无法进行后遍历的,因此取消节点的[后继]为自引用,这也是方
            // 法会从[尾]向前遍历查找其首个未取消后继节点的核心原因。
            node.next = node;
        }
    }

    /**
     * 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.
     * 为失败获取的状态检查并更新状态。如果线程应该阻塞则返回true。这是所有获取循环中的主要信号控制。需要
     * pred == node.prev
     *
     * @param pred node's predecessor holding status 节点持有状态的前驱节点
     * @param node the node 节点
     * @return {@code true} if thread should block 如果线程应该阻塞则返回true
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 在失败获取后应该阻塞
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 判断指定节点在获取状态失败后是否可以进入等待状态,是则返回true;否则返回false,
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会判断指定前驱节点的[等待状态]是否为SIGNAL(-1:信号),是则返回true。因为该状态代表指定前驱
     * 会在释放时唤醒身为其[后继]的指定节点,因为其可以安全的进入等待状态。
     * ---- 如果指定前驱节点的[等待状态]不为SIGNAL(-1:信号),意味着无法保证指定节点进入等待状态后可被唤醒,因
     * 此指定节点不可以进入等待状态,应该返回false。但是在正式返回之前,方法会根据指定前驱节点[等待状态]的不同执
     * 行相应的辅助性质操作。
     * ---- 如果指定前驱节点的[等待状态] > 0,意味着其已因为中断/超时等原因被取消,取消节点是没有实际意义的,因此
     * 此处会执行为指定节点寻找首个未取消前驱节点的辅助操作,以应对下次的是否可以进入等待状态的判断。方法会以指
     * 定前驱节点为起点进行前遍历,找到指定节点的首个未取消前驱节点,并将之设置为指定节点的[前驱],再将指定节点
     * 设置为该首个未取消前驱节点的[后继],令之成为新的指定前驱节点。
     * ---- 如果指定前驱节点的[等待状态]为0或PROPAGATE(-3:传播),同样无法保证指定节点进入等待状态后可被唤醒。
     * 事实上,当指定前驱节点的[等待状态]为0或PROPAGATE(-3:传播)时,身为后继节点的指定节点的线程可能可以在
     * 一定概率上避免进入等待状态,因此0和PROPAGATE(-3:传播)的[等待状态]可能是因为释放状态线程为了唤醒[头]
     * 的后继节点线程而设置的,因此如果指定前驱节点为[头]的话,指定节点可能可以在一定概率上避免进入等待状态,因
     * 为被提前唤醒的线程可以避免进入等待状态。但与此同时0状态也可能是因为前驱节点没有后继节点或后继节点尚未将
     * 之设置为SIGNAL(-1:信号)的原因产生。这种情况下,如果不将之设置为SIGNAL(-1:信号),则进入等待状态的
     * 后继节点线程将可能永远无法被唤醒。因此在这种情况下方法会通过CAS操作将指定前驱节点的[等待状态]设置为
     * SIGNAL(-1:信号),以作为下次调用当前方法时指定节点是否允许进入等待状态的判断条件。此处之所以使用CAS操
     * 作是因为指定前驱节点的[等待状态]存在并发修改可能,例如被外部线程取消,或者其为[头]的话被释放状态线程设置0
     * 或PROPAGATE(-3:传播)等。当CAS操作失败时我们并不需要做任何事情,因为此时的[等待状态]会被方法的调用者
     * 作为判断依据并执行相应的操作。
     */
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        // ---- 方法首先会判断指定前驱节点的[等待状态]是否为SIGNAL(-1:信号),是则返回true。因为该状态代表指定前
        // 驱会在释放时唤醒身为其[后继]的指定节点,因为其可以安全的进入等待状态。
        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;
        }
        // ---- 如果指定前驱节点的[等待状态]不为SIGNAL(-1:信号),意味着无法保证指定节点进入等待状态后可被唤醒,
        // 因此指定节点不可以进入等待状态,应该返回false。但是在正式返回之前,方法会根据指定前驱节点[等待状态]的
        // 不同执行相应的辅助性质操作。
        if (ws > 0) {
            /*
             * Predecessor was cancelled. Skip over predecessors and indicate retry.
             * 前驱节点已被取消,跳过前驱节点并重试。
             */
            // ---- 如果指定前驱节点的[等待状态] > 0,意味着其已因为中断/超时等原因被取消,取消节点是没有实际意义
            // 的,因此此处会执行为指定节点寻找首个未取消前驱节点的辅助操作,以应对下次的是否可以进入等待状态的
            // 判断。方法会以指定前驱节点为起点进行前遍历,找到指定节点的首个未取消前驱节点,并将之设置为指定节
            // 点的[前驱],再将指定节点设置为该首个未取消前驱节点的[后继],令之成为新的指定前驱节点。
            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.
             * 等待状态必须为0或者PROPAGATE(传播)。表示我们需要一个信号,但还没有挂起。调用者将需要再次尝试确
             * 定指定节点线程在挂起前无法获取。
             */
            // ---- 如果指定前驱节点的[等待状态]为0或PROPAGATE(-3:传播),同样无法保证指定节点进入等待状态后可
            // 被唤醒。事实上,当指定前驱节点的[等待状态]为0或PROPAGATE(-3:传播)时,身为后继节点的指定节点的
            // 线程可能可以在一定概率上避免进入等待状态,因此0和PROPAGATE(-3:传播)的[等待状态]可能是因为释放
            // 状态线程为了唤醒[头]的后继节点线程而设置的,因此如果指定前驱节点为[头]的话,指定节点可能可以在一定
            // 概率上避免进入等待状态,因为被提前唤醒的线程可以避免进入等待状态。但与此同时0状态也可能是因为前驱
            // 节点没有后继节点或后继节点尚未将之设置为SIGNAL(-1:信号)的原因产生。这种情况下,如果不将之设置为
            // SIGNAL(-1:信号),则进入等待状态的后继节点线程将可能永远无法被唤醒。因此在这种情况下方法会通过
            // CAS操作将指定前驱节点的[等待状态]设置为SIGNAL(-1:信号),以作为下次调用当前方法时指定节点是否允
            // 许进入等待状态的判断条件。此处之所以使用CAS操作是因为指定前驱节点的[等待状态]存在并发修改可能,例
            // 如被外部线程取消,或者其为[头]的话被释放状态线程设置0或PROPAGATE(-3:传播)等。当CAS操作失败时
            // 我们并不需要做任何事情,因为此时的[等待状态]会被方法的调用者作为判断依据并执行相应的操作。
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
    }

    /**
     * Convenience method to interrupt current thread.
     * 用于中断当前线程的便利方法
     *
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 自我中断
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 中断当前线程
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法调用Thread.currentThread().interrupt()方法将当前线程中断。
     */
    static void selfInterrupt() {
        // 设置线程为中断状态。
        Thread.currentThread().interrupt();
    }

    /**
     * Convenience method to park and then check if interrupted
     * 用于挂起并检查是否中断的便利方法
     *
     * @return {@code true} if interrupted  如果中断则返回true
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 挂起并检查中断
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 令当前线程进入等待状态,并在唤醒后判断其是否被中断,是则返回true;否则返回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会调用LockSupport.park(Object blocker)方法挂起当前线程,以这种方法被挂起的线程会在唤醒后保留中
     * 断状态,因此可以通过Thread.interrupted()方法进行判断线程是否因为中断而被唤醒。
     */
    private final boolean parkAndCheckInterrupt() {
        // ---- 方法首先会调用LockSupport.park(Object blocker)方法挂起当前线程,以这种方法被挂起的线程会在唤醒后保
        // 留中断状态,因此可以通过Thread.interrupted()方法进行判断线程是否因为中断而被唤醒。
        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 如果在等待期间被中断则返回true
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 队列获取
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 为已在同步队列中的指定独占节点获取指定数量的独占状态,如果指定节点线程在等待期间被中断则返回true;否则返
     * 回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法会在死循环中自行,以确保除非在抛出异常的情况下,指定独占节点线程一定可获取到指定数量的独占状态。
     * ---- 方法首先会创建一个中断变量记录指定节点线程是否在方法执行期间被中断,随后判断指定节点的[前驱]是否为头
     * 节点,是则意味着其具备获取独占状态的权限,调用tryAcquire(int arg)方法尝试获取指定数量的独占状态。成功则将
     * 指定节点设置为[头],并将身为旧[头]的[前驱]的[后继]置null,即断开前驱节点与指定节点的关联。最后返回中断变量。
     * ---- 而如果指定节点的前驱节点不是[头]或者尝试获取指定数量的独占状态失败了,则判断指定节点线程是否允许将被
     * 进入等待状态,其本质是判断的其前驱节点的[等待状态]是否为SIGNAL(-1:信号),这期间还包含取消节点节点清理
     * 及设置前驱节点的[等待状态]为SIGNAL(-1:信号)等待操作。如果前驱节点的[等待状态]为SIGNAL(-1:信号)【不
     * 包含此次设置的】,则令指定节点线程进入等待状态。虽说等待操作会执行,但指定节点线程不一定会进入等待状态,
     * 因为如果其前驱节点为[头],并且此时恰好有线程释放了独占状态并指定了对指定节点线程的唤醒,则指定节点线程就
     * 会因为此次唤醒而避免进入等待状态。
     * ---- 当指定节点线程被唤醒后,其会第一时间判断自身是否被中断,是则将中断变量设置为true。而由于当前方法不允
     * 许中断的设定,方法会立即进入下个循环再次执行流程,以确保指定节点线程在没有异常的情况下一定可以获取到执
     * 行数量的独占状态。
     * ---- 方法在执行期间可能因为某些原因而失败,在这种情况下需要将指定节点取消,令之可被后续的节点线程清理。
     */
    final boolean acquireQueued(final Node node, int arg) {
        // ---- 方法会在死循环中自行,以确保除非在抛出异常的情况下,指定独占节点线程一定可获取到指定数量的独占状态。
        boolean failed = true;
        try {
            // ---- 方法首先会创建一个中断变量记录指定节点线程是否在方法执行期间被中断,随后判断指定节点的[前驱]是否
            // 为头节点,是则意味着其具备获取独占状态的权限,调用tryAcquire(int arg)方法尝试获取指定数量的独占状态。
            // 成功则将指定节点设置为[头],并将身为旧[头]的[前驱]的[后继]置null,即断开前驱节点与指定节点的关联。最后
            // 返回中断变量。
            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;
                }
                // ---- 而如果指定节点的前驱节点不是[头]或者尝试获取指定数量的独占状态失败了,则判断指定节点线程是否允
                // 许将被进入等待状态,其本质是判断的其前驱节点的[等待状态]是否为SIGNAL(-1:信号),这期间还包含取消
                // 节点节点清理及设置前驱节点的[等待状态]为SIGNAL(-1:信号)等待操作。如果前驱节点的[等待状态]为
                // SIGNAL(-1:信号)【不包含此次设置的】,则令指定节点线程进入等待状态。虽说等待操作会执行,但指定节
                // 点线程不一定会进入等待状态,因为如果其前驱节点为[头],并且此时恰好有线程释放了独占状态并指定了对指
                // 定节点线程的唤醒,则指定节点线程就会因为此次唤醒而避免进入等待状态。
                // ---- 当指定节点线程被唤醒后,其会第一时间判断自身是否被中断,是则将中断变量设置为true。而由于当前方法
                // 不允许中断的设定,方法会立即进入下个循环再次执行流程,以确保指定节点线程在没有异常的情况下一定可以获
                // 取到执行数量的独占状态。
                if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) {
                    interrupted = true;
                }
            }
        } finally {
            // ---- 方法在执行期间可能因为某些原因而失败,在这种情况下需要将指定节点取消,令之可被后续的节点线程清理。
            if (failed) {
                cancelAcquire(node);
            }
        }
    }

    /**
     * Acquires in exclusive interruptible mode.
     * 在独占可中断模式中获取
     *
     * @param arg the acquire argument 获取参数
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 队列获取
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 将当前线程封装为独占节点加入同步队列中并获取指定数量的独占状态,如果独占状态数量不足则无限等待至存在足够
     * 的独占状态为止。在等待期间如果当前线程被中断则抛出中断异常,且所属独占节点将被取消。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会通过当前线程创建一个独占节点并将之加入同步队列中,随后进入死循环,确保在方法在不抛出异常的
     * 情况下当前线程一定能后获取到指定数量的独占状态。
     * ---- 方法会判断节点的[前驱]是否为[头],是则意味着其具备获取独占状态的权限,调用tryAcquire(int arg)方法尝试获
     * 取指定数量的独占状态。成功则将节点设置为[头],并将身为旧[头]的[前驱]的[后继]置null,即断开前驱节点与节点的
     * 关联,最后返回。
     * ---- 而如果节点的前驱节点不是[头]或者尝试获取数量的独占状态失败了,则判断当前线程是否允许将被进入等待状态,
     * 其本质是判断的其前驱节点的[等待状态]是否为SIGNAL(-1:信号),这期间还包含取消节点节点清理及设置前驱节点
     * 的[等待状态]为SIGNAL(-1:信号)等待操作。如果前驱节点的[等待状态]为SIGNAL(-1:信号)【不包含此次设置的】,
     * 则令当前线程进入等待状态。虽说等待操作会执行,但当前线程不一定会进入等待状态,因为如果其前驱节点为[头],
     * 并且此时恰好有线程释放了独占状态并对当前线程进行了唤醒,则当前线程就会因为此次唤醒而避免进入等待状态。而
     * 当当前线程被唤醒后,其第一时间会判断自身是否被中断,是则抛出中断异常。'
     * ---- 如果当前线程不允许/无法进入等待状态或已被唤醒,则方法会立即进入下个循环再次执行流程,以确保当前线程
     * 在没有异常的情况下一定可以获取到执行数量的独占状态。
     * ---- 方法在执行期间可能因为例如中断的原因而失败,在这种情况下需要将指定节点取消,令之可被后续的节点线程清
     * 理。
     */
    private void doAcquireInterruptibly(int arg) throws InterruptedException {
        // ---- 方法首先会通过当前线程创建一个独占节点并将之加入同步队列中,随后进入死循环,确保在方法在不抛出异
        // 常的情况下当前线程一定能后获取到指定数量的独占状态。
        final Node node = addWaiter(Node.EXCLUSIVE);
        boolean failed = true;
        try {
            for (; ; ) {
                // ---- 方法会判断节点的[前驱]是否为[头],是则意味着其具备获取独占状态的权限,调用tryAcquire(int arg)
                // 方法尝试获取指定数量的独占状态。成功则将节点设置为[头],并将身为旧[头]的[前驱]的[后继]置null,即
                // 断开前驱节点与节点的关联,最后返回。
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return;
                }
                // ---- 而如果节点的前驱节点不是[头]或者尝试获取数量的独占状态失败了,则判断当前线程是否允许将被进
                // 入等待状态,其本质是判断的其前驱节点的[等待状态]是否为SIGNAL(-1:信号),这期间还包含取消节点
                // 节点清理及设置前驱节点的[等待状态]为SIGNAL(-1:信号)等待操作。如果前驱节点的[等待状态]为
                // SIGNAL(-1:信号)【不包含此次设置的】,则令当前线程进入等待状态。虽说等待操作会执行,但当前
                // 线程不一定会进入等待状态,因为如果其前驱节点为[头],并且此时恰好有线程释放了独占状态并对当前线
                // 程进行了唤醒,则当前线程就会因为此次唤醒而避免进入等待状态。而当当前线程被唤醒后,其第一时间会
                // 判断自身是否被中断,是则抛出中断异常。
                // ---- 如果当前线程不允许/无法进入等待状态或已被唤醒,则方法会立即进入下个循环再次执行流程,以确保
                // 当前线程在没有异常的情况下一定可以获取到执行数量的独占状态。
                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 如果获取则返回true
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 执行纳米获取
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 将当前线程封装为独占节点加入同步队列中并获取指定数量的独占状态,如果独占状态数量不足则在指定等待时间内有
     * 限等待至存在足够的独占状态为止。超时指定等待时间则返回false。在等待期间如果当前线程被中断则抛出中断异常,
     * 且所属独占节点将被取消。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会判断指定纳秒超时时间是否 <= 0,是则返回false,因为这意味着可供当前线程获取指定数量独占状态
     * 的时间为0,因此当前方法不允许在执行下去。
     * ---- 如果指定纳秒超时时间 > 0,则通过其计算死亡线,即支持执行的最终时间边界,用于在下述流程中限制方法只在
     * 指定纳秒时间内执行。随后通过当前线程创建独占节点,并将之加入当前AQS的同步队列中。
     * ---- 然后,方法会进入一个死循环,以确保在不抛出异常/执行时间超出指定纳秒超时时间的情况下一定可以获取指定
     * 数量的独占状态。方法会判断节点的[前驱]是否为[头],是则意味着其具备获取独占状态的权限,调用
     * tryAcquire(int arg)方法尝试获取指定数量的独占状态。成功则将节点设置为[头],并将身为旧[头]的[前驱]的[后继]置
     * null,即断开前驱节点与节点的关联,最后返回true,表示当前线程获取指定数量的独占状态成功。
     * ---- 而如果节点的前驱节点不是[头]或者尝试获取数量的独占状态失败了,则计算新指定纳秒超时时间,用于判断当前
     * 时间是否已经超出了最大允许执行时间,即判断新指定纳秒超时时间是否 <= 0,是则返回false,表示当前线程获取指
     * 定数量的独占状态失败。而如果新指定纳秒超时时间 > 0,则判断当前线程是否允许将进入等待状态,其本质是判断的
     * 其前驱节点的[等待状态]是否为SIGNAL(-1:信号),这期间还包含取消节点节点清理及设置前驱节点的[等待状态]为
     * SIGNAL(-1:信号)等待操作。如果前驱节点的[等待状态]为SIGNAL(-1:信号)【不包含此次设置的】,则令当前线
     * 程根据新指定纳秒超时时间进入有限等待状态。但是在正式进入等待状态前,会判断指定纳秒超时时间是否 > [超时自
     * 旋阈值],是则进入有限等待状态;否则略过该操作。之所以会进行此判断是因为线程的等待/唤醒是非常重量级的操作,
     * 在等待时间很短的情况下令线程进入等待状态是一种收益非常低的行为,因此方法会直接略过该操作。此外,即使等待
     * 操作会执行,但当前线程也不一定会进入等待状态,因为如果其前驱节点为[头],并且此时恰好有线程释放了独占状态
     * 并对当前线程进行了唤醒,则当前线程就会因为此次唤醒而避免进入等待状态。
     * ---- 如果当前线程不允许/无法进入等待状态或已被唤醒,则方法会先判断自身是否被中断,是则抛出中断异常。否则
     * 进入下个循环再次执行流程,以确保当前线程在没有异常及未超时的情况下一定可以获取到执行数量的独占状态。
     * --- 方法在执行期间可能因为例如中断/超时的原因而失败,在这种情况下需要将指定节点取消,令之可被后续的节点
     * 线程清理。
     */
    private boolean doAcquireNanos(int arg, long nanosTimeout) throws InterruptedException {
        // ---- 方法首先会判断指定纳秒超时时间是否 <= 0,是则返回false,因为这意味着可供当前线程获取指定数量独占许
        // 可的时间为0,因此当前方法不允许在执行下去。
        if (nanosTimeout <= 0L) {
            return false;
        }
        // ---- 如果指定纳秒超时时间 > 0,则通过其计算死亡线,即支持执行的最终时间边界,用于在下述流程中限制方法只
        // 在指定纳秒时间内执行。随后通过当前线程创建独占节点,并将之加入当前AQS的同步队列中。
        final long deadline = System.nanoTime() + nanosTimeout;
        final Node node = addWaiter(Node.EXCLUSIVE);
        boolean failed = true;
        try {
            for (; ; ) {
                // ---- 然后,方法会进入一个死循环,以确保在不抛出异常/执行时间超出指定纳秒超时时间的情况下一定可以
                // 获取指定数量的独占状态。方法会判断节点的[前驱]是否为[头],是则意味着其具备获取独占状态的权限,调
                // 用tryAcquire(int arg)方法尝试获取指定数量的独占状态。成功则将节点设置为[头],并将身为旧[头]的[前驱]
                // 的[后继]置null,即断开前驱节点与节点的关联,最后返回true,表示当前线程获取指定数量的独占状态成功。
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return true;
                }
                // ---- 而如果节点的前驱节点不是[头]或者尝试获取数量的独占状态失败了,则计算新指定纳秒超时时间,用于
                // 判断当前时间是否已经超出了最大允许执行时间,即判断新指定纳秒超时时间是否 <= 0,是则返回false,表
                // 示当前线程获取指定数量的独占状态失败。而如果新指定纳秒超时时间 > 0,则判断当前线程是否允许将进入
                // 等待状态,其本质是判断的其前驱节点的[等待状态]是否为SIGNAL(-1:信号),这期间还包含取消节点节点
                // 清理及设置前驱节点的[等待状态]为SIGNAL(-1:信号)等待操作。如果前驱节点的[等待状态]为SIGNAL(-1:
                // 信号)【不包含此次设置的】,则令当前线程根据新指定纳秒超时时间进入有限等待状态。但是在正式进入等
                // 待状态前,会判断指定纳秒超时时间是否 > [超时自旋阈值],是则进入有限等待状态;否则略过该操作。之所
                // 以会进行此判断是因为线程的等待/唤醒是非常重量级的操作,在等待时间很短的情况下令线程进入等待状态
                // 是一种收益非常低的行为,因此方法会直接略过该操作。此外,即使等待操作会执行,但当前线程也不一定会
                // 进入等待状态,因为如果其前驱节点为[头],并且此时恰好有线程释放了独占状态并对当前线程进行了唤醒,则
                // 当前线程就会因为此次唤醒而避免进入等待状态。
                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 获取参数
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 执行共享获取
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 将当前线程封装为共享节点加入同步队列中并获取指定数量的共享状态,如果共享状态数量不足则无限等待至存在足够
     * 的独占状态为止。在等待期间如果当前线程被中断不会抛出中断异常,但中断状态会被保留。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会通过当前线程创建共享节点,并加入当前AQS的同步队列中。
     * ---- 然后,方法会进入一个死循环,以确保方法一定可以获取到指定数量的共享状态。随后方法会判断节点的[前驱]是
     * 否为[头],是则意味着其具备获取共享状态的权限,调用tryAcquireShared(int arg)方法尝试获取指定数量的共享状态。
     * 如果方法返回的剩余共享状态 > 0,则说明当前线程获取指定数量的共享状态成功,将共享节点设置为[头]并对[后继]
     * 进行传播,再将身为旧[头]的[前驱]的[后继]置null,即断开前驱节点与节点的关联。这些操作完成后,方法还会根据中
     * 断变量判断当前线程是否被中断过,是则将当前线程中断以保留中断状态再返回;否则直接返回。
     * ---- 而如果共享节点的前驱节点不是[头]或者尝试获取数量的共享状态失败了,则判断当前线程是否允许将进入等待状
     * 态,其本质是判断的其前驱节点的[等待状态]是否为SIGNAL(-1:信号),这期间还包含取消节点节点清理及设置前驱
     * 节点的[等待状态]为SIGNAL(-1:信号)等待操作。如果前驱节点的[等待状态]为SIGNAL(-1:信号)【不包含此次设
     * 置的】,则令当前线程进入无限等待状态。虽说等待操作会执行,但当前线程不一定会进入等待状态,因为如果其前驱
     * 节点为[头],并且此时恰好有线程释放了共享状态并对当前线程进行了唤醒,则当前线程就会因为此次唤醒而避免进入
     * 等待状态。而当当前线程被唤醒后,其第一时间会判断自身是否被中断,是则将中断变量设置为true,随后进入下个
     * 循环再次执行流程,以确保当前线程在没有异常的情况下一定可以获取到执行数量的共享状态。
     * ---- 方法在执行期间可能因为某些原因而失败,在这种情况下需要将指定节点取消,令之可被后续的节点线程清理。
     */
    private void doAcquireShared(int arg) {
        // ---- 方法首先会通过当前线程创建共享节点,并加入当前AQS的同步队列中。
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (; ; ) {
                // ---- 然后,方法会进入一个死循环,以确保方法一定可以获取到指定数量的共享状态。随后方法会判断节点
                // 的[前驱]是否为[头],是则意味着其具备获取共享状态的权限,调用tryAcquireShared(int arg)方法尝试获取
                // 指定数量的共享状态。如果方法返回的剩余共享状态 > 0,则说明当前线程获取指定数量的共享状态成功,
                // 将共享节点设置为[头]并对[后继]进行传播,再将身为旧[头]的[前驱]的[后继]置null,即断开前驱节点与节点
                // 的关联。这些操作完成后,方法还会根据中断变量判断当前线程是否被中断过,是则将当前线程中断以保留
                // 中断状态再返回;否则直接返回。
                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;
                    }
                }
                // ---- 而如果共享节点的前驱节点不是[头]或者尝试获取数量的共享状态失败了,则判断当前线程是否允许将
                // 进入等待状态,其本质是判断的其前驱节点的[等待状态]是否为SIGNAL(-1:信号),这期间还包含取消节
                // 点节点清理及设置前驱节点的[等待状态]为SIGNAL(-1:信号)等待操作。如果前驱节点的[等待状态]为
                // SIGNAL(-1:信号)【不包含此次设置的】,则令当前线程进入无限等待状态。虽说等待操作会执行,但当
                // 前线程不一定会进入等待状态,因为如果其前驱节点为[头],并且此时恰好有线程释放了共享状态并对当前
                // 线程进行了唤醒,则当前线程就会因为此次唤醒而避免进入等待状态。而当当前线程被唤醒后,其第一时间
                // 会判断自身是否被中断,是则将中断变量设置为true,随后进入下个循环再次执行流程,以确保当前线程在
                // 没有异常的情况下一定可以获取到执行数量的共享状态。
                if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) {
                    interrupted = true;
                }
            }
        } finally {
            // ---- 方法在执行期间可能因为某些原因而失败,在这种情况下需要将指定节点取消,令之可被后续的节点线程清
            // 理。
            if (failed) {
                cancelAcquire(node);
            }
        }
    }

    /**
     * Acquires in shared interruptible mode.
     * 在共享可中断模式中获取
     *
     * @param arg the acquire argument 获取参数
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 执行共享可中断获取
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 将当前线程封装为共享节点加入同步队列中并获取指定数量的共享状态,如果共享状态数量不足则无限等待至存在足够
     * 的独占状态为止。在等待期间如果当前线程被中断会抛出中断异常。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先通过当前线程创建一个共享节点,并加入当前AQS的同步队列中。
     * ---- 然后,方法会进入一个死循环,以确保方法在不抛出异常的情况下一定可以获取到指定数量的共享状态。随后方法
     * 会判断节点的[前驱]是否为[头],是则意味着其具备获取共享状态的权限,调用tryAcquireShared(int arg)方法尝试获取
     * 指定数量的共享状态。如果方法返回的剩余共享状态 > 0,则说明当前线程获取指定数量的共享状态成功,将共享节点
     * 设置为[头]并对[后继]进行传播,再将身为旧[头]的[前驱]的[后继]置null,即断开前驱节点与节点的关联,最后返回。
     * ---- 而如果共享节点的前驱节点不是[头]或者尝试获取数量的共享状态失败了,则判断当前线程是否允许将进入等待状
     * 态,其本质是判断的其前驱节点的[等待状态]是否为SIGNAL(-1:信号),这期间还包含取消节点节点清理及设置前驱
     * 节点的[等待状态]为SIGNAL(-1:信号)等待操作。如果前驱节点的[等待状态]为SIGNAL(-1:信号)【不包含此次设
     * 置的】,则令当前线程进入无限等待状态。虽说等待操作会执行,但当前线程不一定会进入等待状态,因为如果其前驱
     * 节点为[头],并且此时恰好有线程释放了共享状态并对当前线程进行了唤醒,则当前线程就会因为此次唤醒而避免进入
     * 等待状态。而当当前线程被唤醒后,其第一时间会判断自身是否被中断,是则抛出中断异常;否则直接进入下个循环再
     * 次执行流程,以确保当前线程在没有异常的情况下一定可以获取到执行数量的共享状态。
     * ---- 方法在执行期间可能因为例如中断等原因失败,在这种情况下需要将指定节点取消,令之可被后续的节点线程清理。
     */
    private void doAcquireSharedInterruptibly(int arg) throws InterruptedException {
        // ---- 方法首先通过当前线程创建一个共享节点,并加入当前AQS的同步队列中。
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            for (; ; ) {
                // ---- 然后,方法会进入一个死循环,以确保方法在不抛出异常的情况下一定可以获取到指定数量的共享状态。
                // 随后方法会判断节点的[前驱]是否为[头],是则意味着其具备获取共享状态的权限,调用
                // tryAcquireShared(int arg)方法尝试获取指定数量的共享状态。如果方法返回的剩余共享状态 > 0,则说明当
                // 前线程获取指定数量的共享状态成功,将共享节点设置为[头]并对[后继]进行传播,再将身为旧[头]的[前驱]
                // 的[后继]置null,即断开前驱节点与节点的关联,最后返回。
                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;
                    }
                }
                // ---- 而如果共享节点的前驱节点不是[头]或者尝试获取数量的共享状态失败了,则判断当前线程是否允许将
                // 进入等待状态,其本质是判断的其前驱节点的[等待状态]是否为SIGNAL(-1:信号),这期间还包含取消节
                // 点节点清理及设置前驱节点的[等待状态]为SIGNAL(-1:信号)等待操作。如果前驱节点的[等待状态]为
                // SIGNAL(-1:信号)【不包含此次设置的】,则令当前线程进入无限等待状态。虽说等待操作会执行,但当
                // 前线程不一定会进入等待状态,因为如果其前驱节点为[头],并且此时恰好有线程释放了共享状态并对当前
                // 线程进行了唤醒,则当前线程就会因为此次唤醒而避免进入等待状态。而当当前线程被唤醒后,其第一时间
                // 会判断自身是否被中断,是则抛出中断异常;否则直接进入下个循环再次执行流程,以确保当前线程在没有
                // 异常的情况下一定可以获取到执行数量的共享状态。
                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 如果获取则返回true
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 执行共享纳米获取
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 将当前线程封装为共享节点加入同步队列中并获取指定数量的共享状态,如果共享状态数量不足则在指定等待时间内有
     * 限等待至存在足够的共享状态为止。超时指定等待时间则返回false。在等待期间如果当前线程被中断则抛出中断异常,
     * 且所属共享节点将被取消。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会判断指定纳秒超时时间是否 <= 0,是则返回false,因为这意味着可供当前线程获取指定数量共享状态
     * 的时间为0,因此当前方法不允许在执行下去。
     * ---- 如果指定纳秒超时时间 > 0,则通过其计算死亡线,即支持执行的最终时间边界,用于在下述流程中限制方法只在
     * 指定纳秒时间内执行。随后通过当前线程创建共享节点,并将之加入当前AQS的同步队列中。
     * ---- 然后,方法会进入一个死循环,以确保在不抛出异常/执行时间超出指定纳秒超时时间的情况下一定可以获取指定
     * 数量的共享状态。方法会判断节点的[前驱]是否为[头],是则意味着其具备获取共享状态的权限,调用
     * tryAcquireShared(int arg)方法尝试获取指定数量的共享状态。成功则将节点设置为[头]并[后继]进行传播,并将身为旧
     * [头]的[前驱]的[后继]置null,即断开前驱节点与节点的关联,最后返回true,表示当前线程获取指定数量的共享状态成
     * 功。
     * ---- 而如果节点的前驱节点不是[头] 或者尝试获取数量的共享状态失败了,则计算新指定纳秒超时时间,用于判断当前
     * 时间是否已经超出了最大允许执行时间,即判断新指定纳秒超时时间是否 <= 0,是则返回false,表示当前线程获取指
     * 定数量的共享状态失败。而如果新指定纳秒超时时间 > 0,则判断当前线程是否允许将进入等待状态,其本质是判断的
     * 其前驱节点的[等待状态] 是否为SIGNAL(-1:信号),这期间还包含取消节点节点清理及设置前驱节点的[等待状态]为
     * SIGNAL(-1:信号)等待操作。如果前驱节点的[等待状态] 为SIGNAL(-1:信号)【不包含此次设置的】,则令当前线
     * 程根据新指定纳秒超时时间进入有限等待状态。但是在正式进入等待状态前,会判断指定纳秒超时时间是否 > [超时自
     * 旋阈值],是则进入有限等待状态;否则略过该操作。之所以会进行此判断是因为线程的等待/唤醒是非常重量级的操作,
     * 在等待时间很短的情况下令线程进入等待状态是一种收益非常低的行为,因此方法会直接略过该操作。此外,即使等待
     * 操作会执行,但当前线程也不一定会进入等待状态,因为如果其前驱节点为[头],并且此时恰好有线程释放了共享状态
     * 并对当前线程进行了唤醒,则当前线程就会因为此次唤醒而避免进入等待状态。
     * ---- 如果当前线程不允许 / 无法进入等待状态或已被唤醒,则方法会先判断自身是否被中断,是则抛出中断异常。否则
     * 进入下个循环再次执行流程,以确保当前线程在没有异常及未超时的情况下一定可以获取到执行数量的共享状态。
     * --- 方法在执行期间可能因为例如中断 / 超时的原因而失败,在这种情况下需要将指定节点取消,令之可被后续的节点
     * 线程清理。
     */
    private boolean doAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException {
        // ---- 方法首先会判断指定纳秒超时时间是否 <= 0,是则返回false,因为这意味着可供当前线程获取指定数量共享状
        // 态的时间为0,因此当前方法不允许在执行下去。
        if (nanosTimeout <= 0L) {
            return false;
        }
        //---- 如果指定纳秒超时时间 > 0,则通过其计算死亡线,即支持执行的最终时间边界,用于在下述流程中限制方法只
        // 在指定纳秒时间内执行。随后通过当前线程创建共享节点,并将之加入当前AQS的同步队列中。
        final long deadline = System.nanoTime() + nanosTimeout;
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            for (; ; ) {
                // ---- 然后,方法会进入一个死循环,以确保在不抛出异常/执行时间超出指定纳秒超时时间的情况下一定可以
                // 获取指定数量的共享状态。方法会判断节点的[前驱]是否为[头],是则意味着其具备获取共享状态的权限,调
                // 用tryAcquireShared(int arg)方法尝试获取指定数量的共享状态。成功则将节点设置为[头]并[后继]进行传播,
                // 并将身为旧[头]的[前驱]的[后继]置null,即断开前驱节点与节点的关联,最后返回true,表示当前线程获取指
                // 定数量的共享状态成功。
                final Node p = node.predecessor();
                if (p == head) {
                    int r = tryAcquireShared(arg);
                    if (r >= 0) {
                        setHeadAndPropagate(node, r);
                        // help GC
                        // 帮助GC
                        p.next = null;
                        failed = false;
                        return true;
                    }
                }
                // ----而如果节点的前驱节点不是[头] 或者尝试获取数量的共享状态失败了,则计算新指定纳秒超时时间,用于判
                // 断当前 时间是否已经超出了最大允许执行时间,即判断新指定纳秒超时时间是否 <= 0,是则返回false,表示当
                // 前线程获取指 定数量的共享状态失败。而如果新指定纳秒超时时间 > 0,则判断当前线程是否允许将进入等待状
                // 态,其本质是判断的 其前驱节点的[等待状态] 是否为SIGNAL(-1:信号),这期间还包含取消节点节点清理及
                // 设置前驱节点的[等待状态] 为 SIGNAL(-1:信号)等待操作。如果前驱节点的[等待状态] 为SIGNAL(-1:信号)
                // 【不包含此次设置的】,则令当前线 程根据新指定纳秒超时时间进入有限等待状态。但是在正式进入等待状态前,
                // 会判断指定纳秒超时时间是否 > [超时自旋阈值],是则进入有限等待状态;否则略过该操作。之所以会进行此判
                // 断是因为线程的等待/唤醒是非常重量级的操作,在等待时间很短的情况下令线程进入等待状态是一种收益非常
                // 低的行为,因此方法会直接略过该操作。此外,即使等待操作会执行,但当前线程也不一定会进入等待状态,因
                // 为如果其前驱节点为[头],并且此时恰好有线程释放了共享状态 并对当前线程进行了唤醒,则当前线程就会因为
                // 此次唤醒而避免进入等待状态。
                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.
     * 尝试在独占模式中获取。该方法应该查询对象的状态是否允许它在独占模式中获取,并且如果允许并获取它。
     * <p>
     * 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()}.
     * 该方法永远通过线程执行获取调用。如果该方法报告失败,则获取方法可能在它尚未排队时排队线程,直至它因为来自
     * 其它线程释放而被通知。该方法可用于实现锁的tryLock()方法。
     * <p>
     * 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.
     * 如果成功则返回true。在成功后,该对象已被获取。
     * @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
     *                                       不支持操作异常:如果独占模式不支持
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 尝试获取
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 令当前线程尝试获取指定数量的独占状态,成功则返回true;否则返回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    protected boolean tryAcquire(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * Attempts to set the state to reflect a release in exclusive mode.
     * 尝试在独占模式中设置状态来映射释放
     * <p>
     * This method is always invoked by the thread performing release.
     * 该方法总是通过线程执行释放来调用
     * <p>
     * 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.
     * 如果当前对象当前处于全释放的状态则返回true,如此任意等待线程可能尝试获取,否则返回false。
     * @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
     *                                       不支持操作异常:如果独占模式不支持
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 尝试释放
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 令当前线程尝试释放指定数量的独占状态,所有独占状态都被释放时返回true;否则返回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    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.
     * 尝试在共享模式中获取。该方法应该查询对象的状态是否允许它在共享模式中获取,并入如果允许则获取它。
     * <p>
     * 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.
     * 该方法总是通过线程执行获取调用。如果当前方法报告失败,则获取方法可能在其尚未排队的情况下排队,直至被来自
     * 其它某些线程释放时传递信号。
     * <p>
     * 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.
     * 失败时返回负值;如果在共享模式中获取成功但随后共享获取无法成功则返回0;并且如果在共享模式中获取成功并且随
     * 后在共享模式中获取依然可能成功则返回正值,在这种情况下一个随后等待的线程必须检查可用性。(支持三种不同的
     * 返回值令该方法在有时只独占获取的上下中使用)
     * @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
     *                                       不支持操作异常:如果共享模式不支持
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 尝试共享释放
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 令当前线程尝试获取当前AQS中指定数量的共享状态,返回值为0/正数表示获取成功,且该正数表示当前AQS的剩余共
     * 享状态总数;返回值为负数则表示获取失败。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    protected int tryAcquireShared(int arg) {
        throw new UnsupportedOperationException();
    }

    /**
     * Attempts to set the state to reflect a release in shared mode.
     * 尝试设置状态反射在共享模式中的释放
     * <p>
     * This method is always invoked by the thread performing release.
     * 该方法总是通过线程执行释放调用。
     * <p>
     * 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
     * 如果该共享模式的释放允许等待中的获取(共享或独占)成功则为true;否则为false。
     * @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
     *                                       不支持操作异常:共享模式不支持
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 尝试共享释放
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 令当前线程尝试释放当前AQS中指定数量的共享状态,所有共享状态都被释放时返回true;否则返回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    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}.)
     * 如果同步被独占持有与当前(调用)线程有关则返回true。该方法在任意调用非等待条件方法后调用。(等待方法转而
     * 调用释放)
     * <p>
     * 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
     * 如果同步被对独占持有则返回true;否则返回fasle。
     * @throws UnsupportedOperationException if conditions are not supported
     *                                       不支持操作异常:如果条件不支持
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 是否独占持有
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 判断当前AQS是否被独占持有,是则返回true;否则返回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    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}.
     * 在独占模式中获取,忽略中断(即不会抛出中断异常)。通过调用至少一次tryAcquire(int arg)方法实现,在成功时返
     * 回。否则该线程会入队,可能重复地阻塞和解除阻塞,调用tryAcquire(int arg)方法直至成功。该方法可用于实现锁的
     * lock()方法。
     *
     * @param arg the acquire argument. This value is conveyed to {@link #tryAcquire} but is otherwise uninterpreted
     *            and can represent anything you like.
     *            获取参数。该值被传输至tryAcquire(int arg)方法,但是没有其他解释,可以表示您喜欢的任何东西。
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 获取
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 令当前线程获取当前AQS指定数量的独占状态,如果当前AQS中的独占状态总数不足则无限等待至足够为止。如果当前
     * 线程在等待期间被中断不会抛出中断异常,但中断状态会被保留。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会进行一次尝试获取。如果获取失败,则将当前线程封装为独占节点并加入同步队列中进行排队获取。当
     * 前线程会在独占状态数量不足的情况下无限等待至存在足够数量的独占节点且自身在同步队列中的优先级最高后被唤醒,
     * 并在成功获取指定数量的独占状态前会一直重复该流程。
     * ---- 当当前线程成功获取到执行数量的独占状态后,会判断其自身是否曾经被中断,是则再次将自身设置为中断状态。
     */
    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}.
     * 在独占模式中获取,如果中断则中止。通过首次检查中断状态时实现,那么至少调用过一次tryAcquire(),成功时返回。
     * 否则线程将被排队,可能重复阻塞和解除阻塞,调用tryAcquire()支持成功或线程被中断。大概方法可被用于实现锁的
     * lockInterruptibly方法。
     *
     * @param arg the acquire argument.  This value is conveyed to {@link #tryAcquire} but is otherwise uninterpreted
     *            and can represent anything you like.
     *            获取参数。该值被传送至tryAcquire方法但它没有其他解释并且可以表示任意你想要的概念。
     * @throws InterruptedException if the current thread is interrupted
     *                              中断异常:如果当前线程被中断
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 可中断获取
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 令当前线程获取当前AQS指定数量的独占状态,如果当前AQS中的独占状态总数不足则无限等待至足够为止。如果当前
     * 线程在等待期间被中断会抛出中断异常。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会判断当前线程是否被中断,是则直接抛出中断异常。否则进行获取一次执行数量的独占状态,成功则直
     * 接结束方法;否则将当前线程封装为独占节点并加入同步队列中进行排队获取。当前线程会在独占状态数量不足的情况
     * 下无限等待至存在足够数量的独占节点且自身在同步队列中的优先级最高后被唤醒,并在成功获取指定数量的独占状态
     * 前会一直重复该流程。
     * ---- 如果方法在执行期间被中断,则会在从等待状态中唤醒后直接抛出中断异常。
     */
    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)}.
     * 尝试在独占模式中获取,如果中断则中止,以及如果指定超时时间消逝则失败。通过首次检查状态实现,那么至少调用
     * 过一次tryAcquire(),并在成功时返回。否则线程将排队,并可能重复阻塞和解除阻塞,直到tryAcquire调用成功或线程
     * 被中断或超时消逝。该方法可用于实现锁的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.
     *                     获取参数。该值被传送至tryAcquire方法但它没有其他解释并且可以表示任意你想要的概念。
     * @param nanosTimeout the maximum number of nanoseconds to wait
     *                     用于等待的最大纳秒时间
     * @return {@code true} if acquired; {@code false} if timed out 如果获取则返回true;如果超时则返回false。
     * @throws InterruptedException if the current thread is interrupted
     *                              中断:如果当前线程中断
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 尝试纳秒获取
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 令当前线程获取当前AQS指定数量的独占状态,如果当前AQS中的独占状态总数不足则在指定等待时间内有限等待至足
     * 够为止,超出指定等待时间则返回false。如果当前线程在等待期间被中断会抛出中断异常。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会判断当前线程是否被中断,是则直接抛出中断异常。否则进行获取一次执行数量的独占状态,成功则直
     * 接结束方法;否则将当前线程封装为独占节点并加入同步队列中进行排队获取。当前线程会在独占状态数量不足的情况
     * 下有限等待至存在足够数量的独占节点且自身在同步队列中的优先级最高后被唤醒,并不断尝试获取指定数量的独占许
     * 可,失败便重新进入等待状态等待下次唤醒,直至成功返回true;或因指定等待时间消逝而返回false。
     * ---- 如果方法在执行期间被中断,则会在从等待状态中唤醒后直接抛出中断异常。
     */
    public final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException {
        // ---- 方法首先会判断当前线程是否被中断,是则直接抛出中断异常。否则进行获取一次执行数量的独占状态,成功
        // 则直接结束方法;否则将当前线程封装为独占节点并加入同步队列中进行排队获取。当前线程会在独占状态数量不
        // 足的情况下有限等待至存在足够数量的独占节点且自身在同步队列中的优先级最高后被唤醒,并不断尝试获取指定
        // 数量的独占状态,失败便重新进入等待状态等待下次唤醒,直至成功返回true;或因指定等待时间消逝而返回false。
        // ---- 如果方法在执行期间被中断,则会在从等待状态中唤醒后直接抛出中断异常。
        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}.
     * 在独占模式中获取。如果tryRelease返回true,则通过解除阻塞一个或多个线程实现。该方法可用于实现锁的unlock方
     * 法。
     *
     * @param arg the release argument.  This value is conveyed to {@link #tryRelease} but is otherwise uninterpreted
     *            and can represent anything you like.
     *            释放参数。该值被传递至tryRelease方法,但其五其它解释,并且可以代表任意你想的概念。
     * @return the value returned from {@link #tryRelease} 从tryRelease中返回的值。
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 释放
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 令当前线程释放当前AQS指定数量的独占状态,如果完全释放则返回true;否则返回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会尝试释放指定数量的独占状态,如果失败则直接返回false。注意,这里的失败有两种情况:一是确实释
     * 放失败;而是没有完全释放,即当前线程持有的独占状态总数大于指定释放的独占状态适量。而如果释放成功,即所有
     * 的独占状态都被释放则获取[头],并且确定[头]存在且存在待唤醒后继节点的情况下对之后继节点进行唤醒,以令之参与
     * 对独占状态的竞争,最后返回true,表示释放成功。
     */
    public final boolean release(int arg) {
        // ---- 方法首先会尝试释放指定数量的独占状态,如果失败则直接返回false。注意,这里的失败有两种情况:一是确
        // 实释放失败;而是没有完全释放,即当前线程持有的独占状态总数大于指定释放的独占状态适量。而如果释放成功,
        // 即所有的独占状态都被释放则获取[头],并且确定[头]存在且存在待唤醒后继节点的情况下对之后继节点进行唤醒,
        // 以令之参与对独占状态的竞争,最后返回true,表示释放成功。
        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.
     * 在共享模式中获取,忽略中断。通过首次至少调用一次tryAcquireShared()方法实现,成功时返回。否则当前线程将排
     * 队,并且可能重复地阻塞和解除阻塞,直至tryAcquireShared()方法成功为止。
     *
     * @param arg the acquire argument.  This value is conveyed to {@link #tryAcquireShared} but is otherwise
     *            uninterpreted and can represent anything you like.
     *            获取参数。该值被传送至tryAcquireShared方法但它没有其他解释并且可以表示任意你想要的概念。
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 获取共享
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 令当前线程获取当前AQS指定数量的共享状态,如果当前AQS中的独占状态总数不足则无限等待至足够为止。如果当前
     * 线程在等待期间被中断不会抛出中断异常,但中断状态会被保留。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法会尝试获取指定数量的共享状态,如果获取成功则直接结束方法;否则将当前线程封装为共享节点加入同步队
     * 列中无限等待。当前线程会在共享状态总数足够且其所属节点的[前驱]为[头]时被唤醒并加入到对共享状态的竞争中,
     * 失败则再次进入等待状态。上述流程会周而复始,直至当前线程成功获取到指定数量的共享状态后结束方法。
     * ---- 在当前线程等待期间如果当前线程被中断不会抛出中断异常,中断状态会被保留。
     */
    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.
     * 在共享中获取,如果中断则中止。如果通过首次检查状态实现,那么至少调用过一次tryAcquireShared方法,成功时返
     * 回。否则线程将排队,并可能重复的阻塞和基础阻塞,调用tryAcquireShared方法直至成功或线程被中断。
     *
     * @param arg the acquire argument. This value is conveyed to {@link #tryAcquireShared} but is otherwise
     *            uninterpreted and can represent anything you like.
     *            获取参数。该值被传递给tryAcquireShared方法但其没有其它节点并且可以代表任意你想的【概念】。
     * @throws InterruptedException if the current thread is interrupted
     *                              中断异常:如果当前线程被中断
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 可中断获取共享
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 令当前线程获取当前AQS指定数量的共享状态,如果当前AQS中的独占状态总数不足则无限等待至足够为止。如果当前
     * 线程在等待期间被中断会抛出中断异常.
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会判断当前线程是否已被中断,是则直接抛出中断异常。
     * ---- 如果当前没有没有被中断,则尝试获取指定数量的共享状态,如果获取成功则直接结束方法;否则将当前线程封装
     * 为共享节点加入同步队列中无限等待。当前线程会在共享状态总数足够且其所属节点的[前驱]为[头]时被唤醒并加入到
     * 对共享状态的竞争中,失败则再次进入等待状态。上述流程会周而复始,直至当前线程成功获取到指定数量的共享状态
     * 后结束方法。
     * ---- 在当前线程等待期间如果当前线程被中断会抛出中断异常。
     */
    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.
     * 尝试在共享模式中获取。如果中断则中止,并入如果指定超时时间消逝则失败。如果通过首次检查中断状态实现则至
     * 少调用了tryAcquireShared一次,并且成功返回。否则线程会被排队,并可能重复阻塞和解除阻塞,直至调用
     * tryAcquireShared方法成功或被中断或超时时间消逝为止。
     *
     * @param arg          the acquire argument. This value is conveyed to {@link #tryAcquireShared} but is otherwise
     *                     uninterpreted and can represent anything you like.
     *                     获取参数。该值被传递给tryAcquireShared方法但其没有其它节点并且可以代表任意你想的【概念】。
     * @param nanosTimeout the maximum number of nanoseconds to wait 用于等待的最大纳秒时间
     * @return {@code true} if acquired; {@code false} if timed out 如果获取成功则返回true;超时则返回false。
     * @throws InterruptedException if the current thread is interrupted
     *                              中断异常:如果当前线程被中断
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 尝试纳秒获取共享
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 令当前线程获取当前AQS指定数量的共享状态,如果当前AQS中的独占状态总数不足则在指定等待时间内有限等待至足
     * 够为止,超出指定等待时间则返回false。如果当前线程在等待期间被中断会抛出中断异常.
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会判断当前线程是否已被中断,是则直接抛出中断异常。
     * ---- 如果当前没有没有被中断,则尝试获取指定数量的共享状态,如果获取成功则直接结束方法;否则将当前线程封装
     * 为共享节点加入同步队列中有限限等待。当前线程会在共享状态总数足够且其所属节点的[前驱]为[头]时被唤醒并加入
     * 到对共享状态的竞争中,失败则再次进入等待状态。上述流程会周而复始,直至当前线程成功获取到指定数量的共享状
     * 态后返回true或因为超时而返回false。
     * ---- 在当前线程等待期间如果当前线程被中断会抛出中断异常。
     */
    public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException {
        // ---- 方法首先会判断当前线程是否已被中断,是则直接抛出中断异常。
        // ---- 如果当前没有没有被中断,则尝试获取指定数量的共享状态,如果获取成功则直接结束方法;否则将当前线程
        // 封装为共享节点加入同步队列中有限限等待。当前线程会在共享状态总数足够且其所属节点的[前驱]为[头]时被唤
        // 醒并加入到对共享状态的竞争中,失败则再次进入等待状态。上述流程会周而复始,直至当前线程成功获取到指定
        // 数量的共享状态后返回true或因为超时而返回false。
        // ---- 在当前线程等待期间如果当前线程被中断会抛出中断异常。
        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.
     * 在共享模式中释放。如果tryReleaseShared方法返回true则通过解锁一个或更多线程实现。
     *
     * @param arg the release argument. This value is conveyed to {@link #tryReleaseShared} but is otherwise
     *            uninterpreted and can represent anything you like.
     *            释放参数。该值被传递给tryReleaseShared方法但没有其它解释,并且可以代表任意你想要的【概念】。
     * @return the value returned from {@link #tryReleaseShared} 从tryReleaseShared中返回的值
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 共享释放
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 令当前线程释放从当前AQS中获取的指定数量的共享状态,当当前线程所有持有的所有共享状态都被释放时返回true;
     * 否则返回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会尝试释放指定数量的共享状态,失败或未完全释放则直接返回false;否则对同步队列中的共享节点进行
     * 唤醒以令之参与对共享状态的竞争中,最后返回true。
     */
    public final boolean releaseShared(int arg) {
        // ---- 方法首先会尝试释放指定数量的共享状态,失败或未完全释放则直接返回false;否则对同步队列中的共享节点
        // 进行唤醒以令之参与对共享状态的竞争中,最后返回true。
        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.
     * 查询是否有线程在等待获取。注意由于中断和超时导致的取消可能在任意时间发生,因此返回值true并不保证有任意其
     * 它线程会永远获取。
     * <p>
     * In this implementation, this operation returns in constant time.
     * 在当前实现中,该操作以常数时间返回。
     *
     * @return {@code true} if there may be other threads waiting to acquire
     * 如果存在可能等待获取的其它线程则返回true。
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 存在排队线程
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 判断当前AQS中是否存在正在等待获取状态的线程,是则返回true;否则返回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法通过判断[头]不等于[尾]判断实现。
     */
    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.
     * 判断是否有线程竞争获取过当前同步器;如果一个获取方法曾经阻塞则为是。
     * <p>
     * In this implementation, this operation returns in constant time.
     * 在当前实现中,该操作以常数时间返回。
     *
     * @return {@code true} if there has ever been contention 如果发生过竞争则为true
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 存在竞争
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 判断当前AQS中是否被线程竞争过,即判断是否有线程为获取当前AQS的状态等待,是则返回true;否则返回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 由于竞争会导致线程尝试获取状态失败,因此方法通过判断[头]是否存在实现。
     */
    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.
     * 返回队列中的首个(最长等待)线程,或者如果当前没有线程在排队则返回null。
     * <p>
     * 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
     * 队列中的首个(最长等待)线程,或者如果当前没有线程在排队则为null
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 获取首个排队线程
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 获取首个排队线程
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会判断[头]是否与[尾]相同,是则直接返回null;否则判断通过两次头部的快速判断获取首个排队线程。如
     * 果两次头部快速判断都因为并发/取消的原因失败了则通过[尾]向前遍历的方式获取首个排队线程。
     */
    public final Thread getFirstQueuedThread() {
        // handle only fast path, else relay
        // 只处理快速路径,否则转发。
        return (head == tail) ? null : fullGetFirstQueuedThread();
    }

    /**
     * Version of getFirstQueuedThread called when fastpath fails
     * 当快速路径失败时调用的getFirstQueuedThread版本
     *
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 全获取首个排队线程
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 获取首个排队线程
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 为了避免在获取首个排队线程时节点出队的并发影响,方法首先会先获取[头]及其[后继],如果两者都不为null且[后
     * 继]的[前驱]为[头]并且[后继]的[线程]不为null则返回[线程]。关于[后继]的[前驱]为[头]的判断可能有些莫名其妙,因为[
     * 后继]本身就是通过[头]得到的,实际上该判断的是避免并发,因为[头]出队会断开两者相互的引用关系。此外判断[线程]
     * 是否为null也是为了避免并发出队和取消等方面的影响。上述整体判断会连续执行两次,试图避免轻度竞争产生的影响。
     * 但如果两次都失败了,则会使用遍历的方式确定首个排队线程。
     * ---- 如果两次整体判断都因为并发/取消的原因失败了,则以[尾]为起点向前遍历。遍历过程中方法会记录每个节点中
     * 不为null的线程,直至遍历到的[头]为止。但实话实话该方案似乎同样会收到的并发的影响,如果记录的线程因为并发
     * 取消而从节点中移除呢?
     */
    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.
         * 首个节点通常是[头]的[后继]。尝试获取它的[线程],确定一致性读取:如果[线程]被置null或者s的[前驱]不是长头
         * 【即该节点以成为新头或已出队,导致其断开了与前驱节点的链接】,那么说明某些其它线程在我们读取期间并发
         * 执行了setHead方法。我们在求助遍历之前二次尝试。
         */

        // ---- 为了避免在获取首个排队线程时节点出队的并发影响,方法首先会先获取[头]及其[后继],如果两者都不为null
        // 且[后继]的[前驱]为[头]并且[后继]的[线程]不为null则返回[线程]。关于[后继]的[前驱]为[头]的判断可能有些莫名其
        // 妙,因为[后继]本身就是通过[头]得到的,实际上该判断的是避免并发,因为[头]出队会断开两者相互的引用关系。
        // 此外判断[线程]是否为null也是为了避免并发出队和取消等方面的影响。上述整体判断会连续执行两次,试图避免
        // 轻度竞争产生的影响。但如果两次都失败了,则会使用遍历的方式确定首个排队线程。
        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.
         * [头]的[后继]可能还没有设置,或者可能在setHead()后未设置。所以如果[尾]是实际的[头]则我们必须检查。如果不
         * 是我们继续,从[尾]安全遍历至[头]以找到首个,保证终止。
         */

        // ---- 如果两次整体判断都因为并发/取消的原因失败了,则以[尾]为起点向前遍历。遍历过程中方法会记录每个节点
        // 中不为null的线程,直至遍历到的[头]为止。但实话实话该方案似乎同样会收到的并发的影响,如果记录的线程因
        // 为并发取消而从节点中移除呢?
        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.
     * 如果指定线程当前正在等待则返回true。
     * <p>
     * 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 如果指定线程在队列中则返回true。
     * @throws NullPointerException if the thread is null
     *                              空指针异常:如果线程为null
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 是否排队
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 判断指定线程是否在等待获取当前AQS的状态,是则返回true;否则返回false。由于并发的原因,该方法返回值无法作
     * 为准确的判断依据。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会判断指定线程是否为null,是则直接抛出空指针异常;否则以[尾]为向[头]遍历,判断指定线程是否存在,
     * 是则返回true;否则返回false。由于并发的原因,该方法返回值无法作为准确的判断依据。
     */
    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.
     * 如果表面上存在首个排队线程在独占模式中等待则返回true。如果该方法返回true,并且当前线程尝试在共享模式中获
     * 取(即当前方法从tryAcquireShared方法中调用)那么它保证当前线程不是首个排队线程。只在可重入读写锁种作为探
     * 索使用。
     *
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 表面上首个排队是否独占
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 判断在当前AQS中等待时间最久的线程要获取的是否是独占状态,是则返回true;否则返回false。该方法可用于在获取
     * 当前AQS共享状态的前提下判断当前线程是否是首个排队线程。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会判断[头]是否不为null,是则继续判断其[后继]是否不为null,是则在再判断[后继]是否为独占节点,是则
     * 再判断[后继]的[线程]是否不为null。如果上述判断全部满足,则说明当前AQS的首个排队线程获取的是独占状态,返回
     * true;否则返回false。
     */
    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.
     * 查询是否存在任意线程等待获取超过当前线程。
     * <p>
     * An invocation of this method is equivalent to (but may be more efficient than):
     * 当前方法调用等待于(但可能更有效)
     * <pre> {@code
     * getFirstQueuedThread() != Thread.currentThread() && hasQueuedThreads()}</pre>
     *
     * <p>
     * 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.
     * 注意:由于中断和超时可能导致取消在任意时间发生,因此返回值true无法保证在当前线程前有其它线程将获取。同样,
     * 其它线程在当前方法由于队列为空而返回false后而排队时有可能的。
     *
     * <p>
     * This method is designed to be used by a fair synchronizer to avoid
     * <a href="AbstractQueuedSynchronizer#barging">barging</a>. 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:
     * 该方法被设计通过公平同步器使用以避免碰撞/冲突。如此如果同步器的当前方法返回true,则其tryAcquire()方法应该
     * 返回false,并且它的tryAcquireShared()方法应该返回一个负值。例如一个公平,可重入,独占模式的同步器的
     * tryAcquire()方法可能像这样:
     * <pre> {@code
     * protected boolean tryAcquire(int arg) {
     *   if (isHeldExclusively()) {
     *     // A reentrant acquire; increment hold count
     *     // 重入获取;增长持有总数
     *     return true;
     *   } else if (hasQueuedPredecessors()) {
     *     // 如果存在前驱节点,则直接返回fale。因为除非被取消,否则前驱节点一定比后继节点更早获取到状态。
     *     return false;
     *   } else {
     *     // try to acquire normally
     *   }
     * }}</pre>
     *
     * @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
     * 如果有排队线程先于当前线程则返回true,以及如果当前线程是队列头节点或者队列为空则返回false。
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 存在排队前驱节点
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 判断当前AQS中是否存在等待时间超过当前线程的线程,是则返回true;否则返回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会判断[头]与[尾]是否不同,是则继续判断[头]的[后继]是否为null,是则继续判断[后继]的[线程]是否不是
     * 当前线程。如果上述判断全都满足,则说明当前AQS中存在等待时间超过当前线程的线程,返回true;否则返回false。
     * @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.
        // 当前正确性依赖于[头]已在[尾]之前初始化,以及如果当前线程在队列中为头,则取决于[尾]的[后继]是否准确。

        // Read fields in reverse initialization order
        // 在逆转初始顺序中读取

        // ---- 方法首先会判断[头]与[尾]是否不同,是则继续判断[头]的[后继]是否为null,是则继续判断[后继]的[线程]是否不
        // 是当前线程。如果上述判断全都满足,则说明当前AQS中存在等待时间超过当前线程的线程,返回true;否则返回
        // false。
        Node t = tail;
        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
     * 等待获取线程的估计值
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 获取队列长度
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 获取在当前AQS中等待获取状态的线程总数的估计值。该方法的返回值不可作为准确的判断依据。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法会以[尾]为起点向前遍历已计算非取消节点的总数并返回。
     */
    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 线程的集
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 获取排队线程集
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 获取在当前AQS中等待获取状态的线程的估计集。该方法的返回值不可作为准确的判断依据。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法会以[尾]为起点向前遍历以获取所有线程置于集中,并最终返回集。
     */
    public final Collection<Thread> getQueuedThreads() {
        ArrayList<Thread> list = new ArrayList<Thread>();
        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.
     * 返回一个包含可能在独占模式中获取的线程的集。这与getQueuedThreads()方法有相同的属性除了它只返回那些由于独
     * 占获取而等待的线程。
     *
     * @return the collection of threads 线程的集
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 获取独占排队线程集
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 获取在当前AQS中等待获取独占状态的线程的估计集。该方法的返回值不可作为准确的判断依据。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法会以[尾]为起点向前遍历以获取所有获取独占状态的线程置于集中,并最终返回集。
     */
    public final Collection<Thread> getExclusiveQueuedThreads() {
        ArrayList<Thread> list = new ArrayList<Thread>();
        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.
     * 返回一个包含可能在共享模式中获取的线程的集。这与getQueuedThreads()方法有相同的属性除了它只返回那些由于共
     * 享获取而等待的线程。
     *
     * @return the collection of threads 线程的集
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 获取共享排队线程集
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 获取在当前AQS中等待获取共享状态的线程的估计集。该方法的返回值不可作为准确的判断依据。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法会以[尾]为起点向前遍历以获取所有获取共享状态的线程置于集中,并最终返回集。
     */
    public final Collection<Thread> getSharedQueuedThreads() {
        ArrayList<Thread> list = new ArrayList<Thread>();
        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.
     * 如果节点(总是初始放置在条件队列中的节点)现在正在等待在同步队列上重新获取,则返回true。
     *
     * @param node the node 节点
     * @return true if is reacquiring 如果重获取则返回true
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 是否在同步队列中
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 判断指定节点是否在当前AQS中等待,是则返回true;否则返回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会判断指定节点的[等待状态]是否为CONDITION(-2:条件)或者[前驱]为null,前者意味着指定节点位于
     * 条件队列中,后者意味着指定节点已从同步队列中出队【可能是单纯的出队,也可能是位于条件队列中】,直接返回
     * false。
     * ---- 如果上述判断不成立,继续判断指定节点的[后继]是否不为null,是则返回true。因为这意味着指定节点存在于同步
     * 队列中且有后继节点。
     * ---- 如果上述判断都不成立,则通过由后向前遍历的方式判断指定节点是否存在于同步队列中。之所以要通过这种方法
     * 遍历是因为指定节点的[前驱]不为null无法保证其位于同步队列中,因为设置[前驱]是将节点加入同步队列的前置操作,
     * [前驱]设置成功后指定节点可能尚未执行CAS排队操作或CAS排队操作失败,因此需要通过遍历来保证绝对正确。
     */
    final boolean isOnSyncQueue(Node node) {
        // ---- 方法首先会判断指定节点的[等待状态]是否为CONDITION(-2:条件)或者[前驱]为null,前者意味着指定节点
        // 位于条件队列中,后者意味着指定节点已从同步队列中出队【可能是单纯的出队,也可能是位于条件队列中】,直
        // 接返回false。
        if (node.waitStatus == Node.CONDITION || node.prev == null) {
            return false;
        }


        // ---- 如果上述判断不成立,继续判断指定节点的[后继]是否不为null,是则返回true。因为这意味着指定节点存在于
        // 同步队列中且有后继节点。

        // If has successor, it must be on queue
        // 如果有后继节点,它必须在队列中。
        if (node.next != null)
            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.
         * 节点前驱可以不为null,因为CAS放置于队列可以失败【也可能还没有执行】的原因其还不存在于同步队列中。所以
         * 我们需要从[尾]开始遍历以确定它实际地标记。在调用该方法时节点总是接近[尾]【即该方法只会在节点执行排队操
         * 作不久后调用】,除非CAS失败(这是不可能的),它会在那里,所以我们很少遍历。
         */
        // ---- 如果上述判断都不成立,则通过由后向前遍历的方式判断指定节点是否存在于同步队列中。之所以要通过这种
        // 方法遍历是因为指定节点的[前驱]不为null无法保证其位于同步队列中,因为设置[前驱]是将节点加入同步队列的前
        // 置操作,[前驱]设置成功后指定节点可能尚未执行CAS排队操作或CAS排队操作失败,因此需要通过遍历来保证绝对
        // 正确。
        return findNodeFromTail(node);
    }

    /**
     * Returns true if node is on sync queue by searching backwards from tail. Called only when needed by isOnSyncQueue.
     * 如果通过从头向前查询发现节点在同步队列中则返回true。只在需要时通过isOnSyncQueue()方法调用。
     *
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 从尾寻找节点
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 判断指定节点是否在当前AQS中等待,是则返回true;否则返回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法会从[尾]向前遍历,如果发现指定节点则返回true;否则返回false。
     */
    private boolean findNodeFromTail(Node node) {
        // ---- 方法会从[尾]向前遍历,如果发现指定节点则返回true;否则返回false。
        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.
     * 从条件队列中迁移节点至同步队列。如果成功则返回true。
     *
     * @param node the node 节点
     * @return true if successfully transferred (else the node was cancelled before signal)
     * 如果传输成功,则为True(否则节点在信号发出前被取消)
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 为信号迁移
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 将指定节点线程唤醒,并将指定节点从条件队列迁移至同步队列中,成功唤醒则返回true;如果指定节点线程将/已因
     * 为中断/超时而唤醒则返回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会尝试将指定节点的[等待状态]由CONDITION(-2:条件)CAS赋值为0。如果CAS赋值失败,意味着指定
     * 节点[线程]将要/已经因为中断/超时而被唤醒,因此直接返回false。
     * ---- 如果指定节点的[等待状态]CAS赋值为0成功,则将该节点迁移至同步队列中,并返回其前驱节点,随后判断前驱节
     * 点是否已被取消或者设置其[等待状态]为SIGNAL(-1:信号)失败。[前驱节点]意味着这需要被清理,而CAS赋值其[等
     * 待状态]为SIGNAL(-1:信号)失败意味着指定节点[线程]不允许处于有限/无限等待状态,因为导致永远无法被唤醒。
     * 因此在这两种情况下唤醒指定节点[线程],令其对已取消的[前驱节点]进行"前驱式清理"或不断尝试将之[等待状态]CAS
     * 赋值为SIGNAL(-1:信号)。
     */
    final boolean transferForSignal(Node node) {
        /*
         * If cannot change waitStatus, the node has been cancelled.
         * 如果无法改变等待状态,则节点已被取消(意思是因为超时/中断而被唤醒)。
         */

        // ---- 方法首先会尝试将指定节点的[等待状态]由CONDITION(-2:条件)CAS赋值为0。如果CAS赋值失败,意味着指定
        // 节点[线程]将要/已经因为中断/超时而被唤醒,因此直接返回false。
        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).
         * 链接至队列并且尝试设置前驱节点的等待状态以表示该线程(可能)正在等待。如果已取消或尝试设置等待状态失败,
         * 唤醒以重同步(在这种情况下等待状态会短暂且无害的错误)
         */

        // ---- 如果指定节点的[等待状态]CAS赋值为0成功,则将该节点迁移至同步队列中,并返回其前驱节点,随后判断前驱
        // 节点是否已被取消或者设置其[等待状态]为SIGNAL(-1:信号)失败。[前驱节点]意味着这需要被清理,而CAS赋值其
        // [等待状态]为SIGNAL(-1:信号)失败意味着指定节点[线程]不允许处于有限/无限等待状态,因为导致永远无法被唤
        // 醒。因此在这两种情况下唤醒指定节点[线程],令其对已取消的[前驱节点]进行"前驱式清理"或不断尝试将之[等待状态]
        // CAS赋值为SIGNAL(-1:信号)。
        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.
     * 如果必要则迁移节点,以在取消等待后同步队列。如果线程在被新传递信号前取消则返回true。
     *
     * @param node the node
     * @return true if cancelled before the node was signalled
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 在等待取消后迁移
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * 将指定节点从条件队列迁移至同步队列中,成功则返回true;如果指定节点将/已被其它独占线程信号唤醒并迁移则返
     * 回false。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ---- 方法首先会尝试将指定节点的[等待状态]由CONDITION(-2:条件)CAS赋值为0,成功意味着指定节点[线程]会因
     * 为超时/中断被唤醒而不会因为信号被唤醒,将指定节点尾插至同步队列中并返回true。
     * ---- 如果CAS失败,意味着有独占AQS的线程将/已对节点执行唤醒,独占AQS的线程会将的指定节点迁移至条件队列中,
     * 因此当前线程/指定节点[线程]会判断指定节点是否位于同步队列中,如果不是则放弃CPU资源进行短暂的运行等待,因
     * 为指定节点被独占AQS的线程迁移至条件队列中是一个很快就会发生的行为。当发现指定节点已位于同步队列中后,方
     * 法会返回false,表示指定节点[线程]是因为信号而被唤醒。
     */
    final boolean transferAfterCancelledWait(Node node) {
        // ---- 方法首先会尝试将指定节点的[等待状态]由CONDITION(-2:条件)CAS赋值为0,成功意味着指定节点[线程]会
        // 因为超时/中断被唤醒而不会因为信号被唤醒,将指定节点尾插至同步队列中并返回true。
        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.
         * 如果我们输给了一个信号,那么我们将无法开展行动直至它入队结束。在一个不完整的迁移中取消是少见和短暂的,
         * 所以只需自旋。
         */

        // ---- 如果CAS失败,意味着有独占AQS的线程将/已对节点执行唤醒,独占AQS的线程会将的指定节点迁移至条件
        // 队列中,因此当前线程/指定节点[线程]会判断指定节点是否位于同步队列中,如果不是则放弃CPU资源进行短暂
        // 的运行等待,因为指定节点被独占AQS的线程迁移至条件队列中是一个很快就会发生的行为。当发现指定节点已
        // 位于同步队列中后,方法会返回false,表示指定节点[线程]是因为信号而被唤醒。
        while (!isOnSyncQueue(node))
            Thread.yield();
        return false;
    }

    /**
     * Invokes release with current state value; returns saved state. Cancels node and throws exception on failure.
     * 随着当前状态调用release()方法,返回被保存的状态。取消节点和在失败的情况下会抛出异常。
     *
     * @param node the condition node for this wait 当前等待的条件节点
     * @return previous sync state 先前的同步状态
     * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
     * 全释放
     * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
     * 清理当前条件对象中条件队列的所有取消节点
     * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
     * ---- 方法首先获取当前独占线程获取的所有[状态],随后将之一次性释放,如果释放成功则直接返回释放的[状态],
     * 否则直接抛出非法状态异常,因为释放理论上是不会失败的。
     * ---- 如果[状态]释放失败了,将节点设置为取消节点。因为这意味着当前方法没有成功的在条件队列中等待,因此其
     * 所在节点理论上应该是无意义的。
     */
    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
     *                                      空指针异常:如果条件为null
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * ---- 获取等待队列长度
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * ---- 获取在指定条件中等待独占获取当前同步器的线程数量估计值。由于在获取期间等待线程数量会因为中断/超时而
     * 发生变化,因此该方法的返回值不能作为准确的判断依据。
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    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<Thread> 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.
     * AQS的条件实现用于充当锁实现的基础。
     * <p>
     * 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}.
     * 该类的方法文档从锁和条件用户的角度描述了机制,而不是行为规范。这个类的导出版本通常需要附带描述依赖于相
     * 关AbstractQueuedSynchronizer的条件语义的文档。
     * <p>
     * This class is Serializable, but all fields are transient, so deserialized conditions have no waiters.
     * 该类是序列化的,但所有字段被修饰了transient,所以反序列化的条件没有等待者。
     *
     * @Description: ----------------------------------------------------------- 名称 -----------------------------------------------------------
     * 条件对象
     * @Description: ----------------------------------------------------------- 作用 -----------------------------------------------------------
     * ----
     * @Description: ----------------------------------------------------------- 逻辑 -----------------------------------------------------------
     * ----
     */
    public class ConditionObject implements Condition, Serializable {

        private static final long serialVersionUID = 1173984872572414699L;
        /**
         * First node of condition queue.
         * 条件队列的头节点
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 首个等待者
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 持有当前条件队列中首个节点的引用
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        private transient Node firstWaiter;
        /**
         * Last node of condition queue.
         * 条件队列的最后节点
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 最后等待者
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 持有当前条件队列中最后节点的引用
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        private transient Node lastWaiter;

        /**
         * Creates a new {@code ConditionObject} instance.
         * 创建一个新条件对象实例
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 条件对象
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 创建条件对象
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        public ConditionObject() {
        }

        // Internal methods
        // 内部方法

        /**
         * Adds a new waiter to wait queue.
         * 新增一个新等待者至等待队列
         *
         * @return its new wait node 它sd的新等待节点
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 新增条件等待者
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 将当前封装为节点并加入当前条件对象的条件队列中
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法首先会获取[最后等待者],如果[最后等待者]存在且已被取消则触发清理条件队列中的所有取消节点,随后
         * 重新获取[最后等待者]。注意,由于取消的并发性,即使在经历过清理后也无法保证条件队列中不存在取消节点,因
         * 为节点可能在清理的过程中被取消,甚至于重新获取的[最后等待者]依然是一个取消节点...清理的目的是为了将取消
         * 节点的数量控制在一个先对较低的数量级。
         * ---- 获取[最后等待着]后,方法会基于当前线程创建一个[等待状态]为CONDITION(-2:条件)的节点,并将之加入到
         * 条件队列中成为[最后等待者],如果当前条件队列中没有其它节点的话则其还需要被设置为[首个等待者]。该过程不
         * 需要CAS的保护,因为该操作只有以独占模式获取[状态]的当前线程才可以操作,因此不会出现并发。
         */
        private Node addConditionWaiter() {
            // ---- 方法首先会获取[最后等待者],如果[最后等待者]存在且已被取消则触发清理条件队列中的所有取消节点,随
            // 后重新获取[最后等待者]。注意,由于取消的并发性,即使在经历过清理后也无法保证条件队列中不存在取消节点,
            // 因为节点可能在清理的过程中被取消,甚至于重新获取的[最后等待者]依然是一个取消节点...清理的目的是为了将
            // 取消节点的数量控制在一个先对较低的数量级。
            Node t = lastWaiter;
            if (t != null && t.waitStatus != Node.CONDITION) {
                unlinkCancelledWaiters();
                t = lastWaiter;
            }
            // ---- 获取[最后等待着]后,方法会基于当前线程创建一个[等待状态]为CONDITION(-2:条件)的节点,并将之加入
            // 到条件队列中成为[最后等待者],如果当前条件队列中没有其它节点的话则其还需要被设置为[首个等待者]。该过
            // 程不需要CAS的保护,因为该操作只有以独占模式获取[状态]的当前线程才可以操作,因此不会出现并发。
            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 条件队列中的首个节点
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 执行唤醒
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 唤醒在当前条件对象中等待的首个线程。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 指定节点为条件队列的[首个等待者],方法首先指定节点的[后继等待者]设置为新[首个等待者],该行为相当于
         * 将指定节点从条件队列中移除。随后如果新[首个等待者]为null,则说明条件队列中已无等待者,再将[最后等待者]
         * 赋值为null。完成对指定等待者的移除后,方法会将其[后继等待者]赋值为null,相当于断开了指定等待者与条件队
         * 列的关联。
         * ----- 接下来方法会调用transferForSignal(Node node)方法唤醒指定等待者[线程],如果因为等待者已被取消而唤醒
         * 失败,则会将新[首个等待者]作为新指定等待者重复执行,直至成功唤醒[首个等待者][线程]为止。
         */
        private void doSignal(Node first) {
            // ---- 指定节点为条件队列的[首个等待者],方法首先指定节点的[后继等待者]设置为新[首个等待者],该行为相当
            // 于将指定节点从条件队列中移除。随后如果新[首个等待者]为null,则说明条件队列中已无等待者,再将[最后等
            // 待者]赋值为null。完成对指定等待者的移除后,方法会将其[后继等待者]赋值为null,相当于断开了指定等待者与
            // 条件队列的关联。
            // ----- 接下来方法会调用transferForSignal(Node node)方法唤醒指定等待者[线程],如果因为等待者已被取消而唤
            // 醒失败,则会将新[首个等待者]作为新指定等待者重复执行,直至成功唤醒[首个等待者][线程]为止。
            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 条件队列中的首个节点
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 执行全唤醒
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 唤醒在当前条件对象中等待的所有线程。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法首先会将的[首个/最后等待者]赋值为null,该行为的作用是将所有的等待者从条件队列中移除。随后方法会
         * 遍历等待者链并依次对所有的[线程]都进行唤醒,直至将除取消等待者以外的所有[线程]都唤醒为止。
         */
        private void doSignalAll(Node first) {
            // ---- 方法首先会将的[首个/最后等待者]赋值为null,该行为的作用是将所有的等待者从条件队列中移除。随后方
            // 法会遍历等待者链并依次对所有的[线程]都进行唤醒,直至将除取消等待者以外的所有[线程]都唤醒为止。
            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.
         * 从条件队列中断开已取消等待节点的链接。只在持有锁期间被调用。当取消在条件等待期间发生,以及一个新等待
         * 者在最后等待者看起来已被取消时插入时调用。该方法需要避免垃圾在缺失信号时遗留。所以即使它可能需要一个完
         * 整的遍历,但也只会在缺失信号时在超时或取消发生时开始运行。它会遍历所有的节点而不是在指定目标处停止以断
         * 开所有垃圾节点的指针而不需要在取消爆发式多次取消。
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 断开已取消的等待者
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 清理当前条件对象中条件队列的所有取消节点
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法首先会获取[首个等待者],随后完整遍历整个条件队列,并移除其中所有已取消的节点。
         */
        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}
         *                                      非法监视状态异常:如果isHeldExclusively()返回false
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 断开已取消的等待者
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 清理当前条件对象中条件队列的所有取消节点
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 如果当前线程不是独占AQS的线程,直接报错,因为只有独占AQS的线程才可以对条件对象进行操作。
         * ---- 如果当前线程是独占AQS的线程,则唤醒条件队列的[首个等待者][线程],该等待者[线程]是所有等待者[线程]中
         * 等待时间最长的。
         */
        @Override
        public final void signal() {
            // ---- 如果当前线程不是独占AQS的线程,直接报错,因为只有独占AQS的线程才可以对条件对象进行操作。
            if (!isHeldExclusively()) {
                throw new IllegalMonitorStateException();
            }
            // ---- 如果当前线程是独占AQS的线程,则唤醒条件队列的[首个等待者][线程],该等待者[线程]是所有等待者[线
            // 程]中等待时间最长的。
            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}
         *                                      非法监视状态异常:如果isHeldExclusively()返回false
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 断开已取消的等待者
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 清理当前条件对象中条件队列的所有取消节点
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 如果当前线程不是独占AQS的线程,直接报错,因为只有独占AQS的线程才可以对条件对象进行操作。
         * ---- 如果当前线程是独占AQS的线程,则唤醒条件队列的[首个等待者][线程],该等待者[线程]是所有等待者[线程]中
         * 等待时间最长的。
         */
        @Override
        public final void signalAll() {
            // ---- 如果当前线程不是独占AQS的线程,直接报错,因为只有独占AQS的线程才可以对条件对象进行操作。
            if (!isHeldExclusively()) {
                throw new IllegalMonitorStateException();
            }
            // ---- 如果当前线程是独占AQS的线程,唤醒条件队列中的所有等待者[线程]。
            Node first = firstWaiter;
            if (first != null) {
                doSignalAll(first);
            }
        }

        /**
         * Implements uninterruptible condition wait.
         * 实现不可中断的条件等待
         * <ol>
         * <li> Save lock state returned by {@link #getState}.
         * 保存通过getState()方法返回的锁状态。
         * <li> Invoke {@link #release} with saved state as argument, throwing IllegalMonitorStateException if it fails.
         * 随着保存的状态作为参数调用release()方法,如果失败则抛出非法监视状态异常。
         * <li> Block until signalled.
         * 阻塞直至收到信号。
         * <li> Reacquire by invoking specialized version of {@link #acquire} with saved state as argument.
         * 通过调用随着保存的状态作为参数调用指定的版本来进行重获取。
         * </ol>
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 等待(不可中断)
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 令当前线程释放所有状态后在当前条件对象中等待,直至被唤醒后重新获取释放的所有状态。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法首先会将当前独占线程封装为等待着加入条件队列中,随后一次性将这些[状态]全部释放,该行为意味着当
         * 前独占线程解除了对AQS的独占,也意味着会有其它线程对[状态]进行竞争。
         * ---- 随后方法会判断当前等待者是否位于同步队列中,等待者会位于同步队列中说明有独占AQS的线程对之进行了迁
         * 移并对[线程]执行了唤醒。如果不位于同步队列中,说明当前等待者依然位于条件队列中,因此其[线程]需要进入有
         * 限/无限等待状态。
         * ---- 进入有限/无限等待状态的等待者[线程]可能因为中断而被唤醒,由于当前方法在设计上不可被中断,即不会响
         * 应中断,因此被唤醒后的等待者[线程]不会抛出中断异常,而是判断等待者是否位于同步队列中。如果不是则再次进
         * 入有限/无限等待状态;否则说明其以被再次加入对[状态]的竞争。
         * ---- 等待者加入同步队列后[线程]会执行对[状态]的获取。此次获取与之前不同,会直接一次获取释放的所有[状态],
         * 获取成功后如果发现当前线程曾经经历过中断,则便将[线程]的中断状态设置为true。
         */
        @Override
        public final void awaitUninterruptibly() {
            // ---- 方法首先会将当前独占线程封装为等待着加入条件队列中,随后一次性将这些[状态]全部释放,该行为意味
            // 着当前独占线程解除了对AQS的独占,也意味着会有其它线程对[状态]进行竞争。
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            // ---- 随后方法会判断当前等待者是否位于同步队列中,等待者会位于同步队列中说明有独占AQS的线程对之进行
            // 了迁移并对[线程]执行了唤醒。如果不位于同步队列中,说明当前等待者依然位于条件队列中,因此其[线程]需
            // 要进入有限/无限等待状态。
            // ---- 进入有限/无限等待状态的等待者[线程]可能因为中断而被唤醒,由于当前方法在设计上不可被中断,即不会
            // 响应中断,因此被唤醒后的等待者[线程]不会抛出中断异常,而是判断等待者是否位于同步队列中。如果不是则
            // 再次进入有限/无限等待状态;否则说明其以被再次加入对[状态]的竞争。
            boolean interrupted = false;
            while (!isOnSyncQueue(node)) {
                LockSupport.park(this);
                if (Thread.interrupted()) {
                    interrupted = true;
                }
            }
            // ---- 等待者加入同步队列后[线程]会执行对[状态]的获取。此次获取与之前不同,会直接一次获取释放的所有[状
            // 态],获取成功后如果发现当前线程曾经经历过中断,则便将[线程]的中断状态设置为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
         * 模式意味着从等待中退出时重中断
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 重中断
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 该标志意味着当线程因为中断而唤醒时需要保留中断状态
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        private static final int REINTERRUPT = 1;
        /**
         * Mode meaning to throw InterruptedException on exit from wait
         * 模式意味着从等待中退出时抛出中断异常
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 重中断
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 该标志意味着当线程因为中断而唤醒时需要抛出中断异常
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        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.
         * 检查中断,如果在被信号通知前中断则返回THROW_IE,如果在信号通知后中断则返回REINTERRUPT,或者如果未
         * 中断则返回0。
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 检查等待期间中断
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 检查当前线程是否在等待期间被中断,如果在唤醒前被中断则返回THROW_IE(-1);如果在唤醒后被中断则返回
         * REINTERRUPT(1);如果未中断则返回0。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ----
         */
        private int checkInterruptWhileWaiting(Node node) {
            // ---- 方法首先会令当前线程相应中断,如果当前线程未被中断则直接返回0;否则继续
            return Thread.interrupted() ? (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) : 0;
        }

        /**
         * Throws InterruptedException, reinterrupts current thread, or does nothing, depending on mode.
         * 根据模式抛出异常,重中断当前线程或什么也不做。
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 在等待后记录中断
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 根据线程的唤醒方式抛出异常、自我中断或什么也不做。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法首先会判断指定中断模式是否为抛出THROW_IE,是则说明当前线程是因为中断而被唤醒,或者更准确的说
         * '是自身将节点的[等待状态]由Condition(-2:条件)CAS赋值为0;因此需要抛出中断异常;而如果指定中断模式为
         * REINTERRUPT,则意味着当前线程在被信号唤醒后又遭遇了中断,因此需要还原中断状态;而如果都不是,则意味
         * 着当前线程是被信号唤醒且整个过程中都未曾经历过中断,因此什么也不做。
         */
        private void reportInterruptAfterWait(int interruptMode) throws InterruptedException {
            if (interruptMode == THROW_IE) {
                // 直接抛出异常。
                throw new InterruptedException();
            } else if (interruptMode == REINTERRUPT) {
                // 自我中断。
                selfInterrupt();
            }

        }

        /**
         * Implements interruptible condition wait.
         * 实现可中断条件等待。
         * <ol>
         * <li> If current thread is interrupted, throw InterruptedException.
         * 如果线程已被中断,抛出中断异常。
         * <li> Save lock state returned by {@link #getState}.
         * 保存通过getState()方法返回的锁状态。
         * <li> Invoke {@link #release} with saved state as argument, throwing IllegalMonitorStateException if it fails.
         * 随着保存的状态作为参数调用release()方法,如果失败则抛出非法状态异常。
         * <li> Block until signalled or interrupted.
         * 阻塞直至被通知或被中断。
         * <li> Reacquire by invoking specialized version of {@link #acquire} with saved state as argument.
         * 通过随保存的状态作为参数调用acquire()方法的指定版本重获取。
         * <li> If interrupted while blocked in step 4, throw InterruptedException.
         * 如果在阻塞至步骤四时被中断则抛出中断异常。
         * </ol>
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 等待
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 令当前线程以独占模式释放所有的状态后在当前条件对象中无限等待,直至因为信号/中断而被唤醒并重新获取之前
         * 释放的所有状态。在成功获取状态后,如果存在中断并发的情况下,如果当前线程因为信号而唤醒则需要保留中断
         * 状态;否则抛出中断异常。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法首先会判断当前线程是否被中断,是则直接抛出中断异常。因为当前方法的设定就是要在中断时抛出中断
         * 异常。随后方法会将当前线程封装为独占节点加入条件队列中,并释放所有的[状态],这一步之后其它线程便可以
         * 对[状态]进行竞争。
         * ---- 这之后方法会循环判断独占节点是否位于同步队列中,条件队列中的独占节点会位于同步队列中是因为其会被
         * 当前线程或AQS独占线程迁移。如果是首次判断发现独占节点位于同步队列中,由于此时当前线程还未进入有限/
         * 无限等待状态,因此独占节点只可能是被AQS独占线程迁移。而如果是非首次判断发现独占节点位于同步队列中,
         * 则可能是被当前线程或AQS独占线程迁移。
         * ---- 独占节点位于同步队列中意味着当前线程已重新参与对[状态]的竞争,因此如果独占节点位于同步队列中则当
         * 前线程应该执行等待流程已获取[状态]。而如果独占节点不位于同步队列中则意味着当前线程需要进入有限/无限
         * 等待状态直到被主动/被动的唤醒。被唤醒的当前线程会判断自身因为什么而唤醒,如果是因为中断而唤醒,则当
         * 前方法会抛出中断异常;而如果是因为信号而唤醒,则当前线程并不会做什么。但是如果两种唤醒方式出现并发,
         * 则以成功将独占节点的[等待状态]由CONDITION(-2:条件)CAS赋值为0的唤醒方式为准。
         * ---- 事实上,这里会进行独占节点是否位于同步队列的判断就是一个很令人疑惑的问题,因为理论上只要当前线程
         * 进入有限/无限等待状态中,则无论是因为信号/中断/超时而被唤醒都意味着其必然会被迁移至同步队列中。其中
         * 信号唤醒会在AQS独占线程将独占节点迁移至队列后执行,而中断/超时唤醒发生时虽然独占节点依然处于条件队
         * 列中,但后续也会立即执行,即当前线程必然会在判断独占节点是否位于同步队列之前将之迁移至同步队列中,因
         * 此从逻辑上来说似乎完全没有判断的必要,更不要说还是循环判断。
         * ---- 循环判断独占节点是否位于同步队列中的根本目的是为了避免虚假唤醒,即避免当前线程在条件为达成的情况
         * 下被唤醒,而所谓的条件自然是独占节点位于同步队列中。事实上,正常情况下当前线程因为信号/中断/超时的原
         * 因被唤醒是不会出现虚拟唤醒的,即正常情况下当前线程被唤醒后独占节点必然已经处于同步队列中,具体原因上
         * 文已经上述过。而之所以会出现虚拟唤醒的情况是由于外部条件的影响而使得当前线程无法进入有限/无限等待状
         * 态或被以外唤醒,而这个就与AQS对线程使用的等待/唤醒工具类LockSupport的机制有关。
         * ---- LockSupport通过park/unpark方法等待/唤醒线程,但与常规等待/唤醒不同的是LockSupport存在许可的概念。
         * 线程最多可以持有一个许可,当线程持有的许可数量 < 0时线程就会进入有限/无限等待状态,因此park/unpark方
         * 法本质上就是在递减/递增线程的许可。线程的默认许可数为0,因此该状态下当对其执行park方法时线程就会因为
         * 许可数 < 0而进入有限/无限等待状态,而在当对其执行unpark()方法时就会使得许可数为0而唤醒。这种情况属于
         * 正常思维下的标准流程,但除此之外还存在一些相对不标准的流程,即如果先对线程执行被unpark()方法而使得许
         * 可数量为1,则在对其执行park()方法时也只能使其为许可数量为0而无法进入有限/无限等待状态。而这就是造成虚
         * 假唤醒的根本原因。
         * ---- 虚假唤醒并不是AQS内部对线程执行LockSupport.park/unpark方法导致的,因为上文已经说过信号唤醒只有在
         * 成功将独占节点迁移至同步队列后才会执行,因此这种情况当前线程如论时具备许可而无法进入有限/无限等待状态
         * 还是被唤醒都必然保证了独占节点位于同步队列中,因此虚假唤醒的情况实际上是由外部的其它线程对当前线程执
         * 行LockSupport.unpark()方法造成的。这种LockSupport.unpark()方法的执行不受AQS内部逻辑的控制,因此就可能
         * 导致线程在独占节点未迁移至同步队列的情况下无法进入有限/无限等待状态或被唤醒。并且由于这种方法的次数和
         * 时机都无法被预知,因此一次判断是不够的,必须循环判断到达成条件为止。循环判断的存在使得外部唤醒无论被
         * 执行了多少次都能够保证线程不会在为达成条件的情况下尝试重新能获取状态,即使其可能只是在不断的自旋而不
         * 是进入有限/无限状态。
         * ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所有[
         * 状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状态]期
         * 间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:重中断),
         * 意味着在整体流程结束后需要重新线程中断以保持中断状态。
         * ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独占
         * 节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所移除,
         * 因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null同时也意
         * 味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样的节点虽然不
         * 是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断唤醒的情况,独占
         * 节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。
         * ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断。
         */
        @Override
        public final void await() throws InterruptedException {
            // ---- 方法首先会判断当前线程是否被中断,是则直接抛出中断异常。因为当前方法的设定就是要在中断时抛出中
            // 断异常。随后方法会将当前线程封装为独占节点加入条件队列中,并释放所有的[状态],这一步之后其它线程便
            // 可以对[状态]进行竞争。
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            int savedState = fullyRelease(node);
            int interruptMode = 0;
            // ---- 这之后方法会循环判断独占节点是否位于同步队列中,条件队列中的独占节点会位于同步队列中是因为其会
            // 被当前线程或AQS独占线程迁移。如果是首次判断发现独占节点位于同步队列中,由于此时当前线程还未进入有
            // 限/无限等待状态,因此独占节点只可能是被AQS独占线程迁移。而如果是非首次判断发现独占节点位于同步队
            // 列中,则可能是被当前线程或AQS独占线程迁移。
            // ---- 独占节点位于同步队列中意味着当前线程已重新参与对[状态]的竞争,因此如果独占节点位于同步队列中则
            // 当前线程应该执行等待流程已获取[状态]。而如果独占节点不位于同步队列中则意味着当前线程需要进入有限/
            // 无限等待状态直到被主动/被动的唤醒。被唤醒的当前线程会判断自身因为什么而唤醒,如果是因为中断而唤醒,
            // 则当前方法会抛出中断异常;而如果是因为信号而唤醒,则当前线程并不会做什么。但是如果两种唤醒方式出现
            // 并发,则以成功将独占节点的[等待状态]由CONDITION(-2:条件)CAS赋值为0的唤醒方式为准。
            // ---- 事实上,这里会进行独占节点是否位于同步队列的判断就是一个很令人疑惑的问题,因为理论上只要当前线
            // 程进入有限/无限等待状态中,则无论是因为信号/中断/超时而被唤醒都意味着其必然会被迁移至同步队列中。
            // 其中信号唤醒会在AQS独占线程将独占节点迁移至队列后执行,而中断/超时唤醒发生时虽然独占节点依然处于
            // 条件队列中,但后续也会立即执行,即当前线程必然会在判断独占节点是否位于同步队列之前将之迁移至同步队
            // 列中,因此从逻辑上来说似乎完全没有判断的必要,更不要说还是循环判断。
            // ---- 循环判断独占节点是否位于同步队列中的根本目的是为了避免虚假唤醒,即避免当前线程在条件为达成的情
            // 况下被唤醒,而所谓的条件自然是独占节点位于同步队列中。事实上,正常情况下当前线程因为信号/中断/超时
            // 的原因被唤醒是不会出现虚拟唤醒的,即正常情况下当前线程被唤醒后独占节点必然已经处于同步队列中,具体
            // 原因上文已经上述过。而之所以会出现虚拟唤醒的情况是由于外部条件的影响而使得当前线程无法进入有限/无
            // 限等待状态或被以外唤醒,而这个就与AQS对线程使用的等待/唤醒工具类LockSupport的机制有关。
            // ---- LockSupport通过park/unpark方法等待/唤醒线程,但与常规等待/唤醒不同的是LockSupport存在许可的概
            // 念。线程最多可以持有一个许可,当线程持有的许可数量 < 0时线程就会进入有限/无限等待状态,因此
            // park/unpark方法本质上就是在递减/递增线程的许可。线程的默认许可数为0,因此该状态下当对其执行park方
            // 法时线程就会因为许可数 < 0而进入有限/无限等待状态,而在当对其执行unpark()方法时就会使得许可数为0而
            // 唤醒。这种情况属于正常思维下的标准流程,但除此之外还存在一些相对不标准的流程,即如果先对线程执行被
            // unpark()方法而使得许可数量为1,则在对其执行park()方法时也只能使其为许可数量为0而无法进入有限/无限等
            // 待状态。而这就是造成虚假唤醒的根本原因。
            // ---- 虚假唤醒并不是AQS内部对线程执行LockSupport.park/unpark方法导致的,因为上文已经说过信号唤醒只有
            // 在成功将独占节点迁移至同步队列后才会执行,因此这种情况当前线程如论时具备许可而无法进入有限/无限等待
            // 状态还是被唤醒都必然保证了独占节点位于同步队列中,因此虚假唤醒的情况实际上是由外部的其它线程对当前
            // 线程执行LockSupport.unpark()方法造成的。这种LockSupport.unpark()方法的执行不受AQS内部逻辑的控制,因
            // 此就可能导致线程在独占节点未迁移至同步队列的情况下无法进入有限/无限等待状态或被唤醒。并且由于这种
            // 方法的次数和时机都无法被预知,因此一次判断是不够的,必须循环判断到达成条件为止。循环判断的存在使得
            // 外部唤醒无论被执行了多少次都能够保证线程不会在为达成条件的情况下尝试重新能获取状态,即使其可能只是
            // 在不断的自旋而不是进入有限/无限状态。
            while (!isOnSyncQueue(node)) {
                LockSupport.park(this);
                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                    break;
            }
            // ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所
            // 有[状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状
            // 态]期间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:
            // 重中断),意味着在整体流程结束后需要重新线程中断以保持中断状态。
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            // clean up if cancelled
            // 如果取消则清理

            // ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独
            // 占节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所
            // 移除,因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null
            // 同时也意味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样
            // 的节点虽然不是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断
            // 唤醒的情况,独占节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            // ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断。
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
        }

        /**
         * Implements timed condition wait.
         * 实现定时的条件等待。
         * <ol>
         * <li> If current thread is interrupted, throw InterruptedException.
         * 如果当前线程被中断,抛出中断异常。
         * <li> Save lock state returned by {@link #getState}.
         * 保存通过getState()方法返回的锁状态。
         * <li> Invoke {@link #release} with saved state as argument, throwing IllegalMonitorStateException if it fails.
         * 将保存的锁状态作为参数调用release()方法,如果失败抛出非法监视状态异常。
         * <li> Block until signalled, interrupted, or timed out.
         * 阻塞直至收到信号,中断,或超时。
         * <li> Reacquire by invoking specialized version of {@link #acquire} with saved state as argument.
         * 通过将保存的锁状态作为桉树调用指定的acquire()方法版本获取状态。
         * <li> If interrupted while blocked in step 4, throw InterruptedException.
         * 如果在步骤四阻塞期间被中断,抛出中断异常。
         * </ol>
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 等待纳秒
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 令当前线程以独占模式释放所有的状态后在当前条件对象中有限等待,直至因为信号/中断/超时而被唤醒并重新获
         * 取之前释放的所有状态并返回剩余等待时间。在成功获取状态后,如果存在中断并发的情况下,如果当前线程因为
         * 信号而唤醒则需要保留中断状态;否则抛出中断异常。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法首先会判断当前线程是否被中断,是则直接抛出中断异常免,否则将当前线程封装为[等待状态]为
         * CONDITION(-2:条件)的独占节点尾插至条件队列中。
         * ---- 随后当前线程会以独占模式释放当前持有的所有[状态],该行为意味着其解除了对AQS的独占,因此从此处开始
         * 将由线程并发的竞争获取[状态]。
         * ---- 计算方法的等待截止时间戳,随后进入判断独占节点是否位于同步队列的循环。在循环中,当前线程首先会判断
         * 等待时间是否超时,是则强制插入至同步队列中并结束循环;否则判断剩余的等待时间是否 >= 自旋阈值。是则进入
         * 令自身进入进入有限等待状态;否则继续执行循环。因为如果等待时间非常短的话等待就是不值得的,因为Java线
         * 程状态的转换也是一件相当耗时耗力的行为,还不如直接自旋等待。
         * ---- 当前线程因为信号/中断/超时等待原因后,会判断自身时因为信号/超时而唤醒还是因为中断而唤醒,已决定在
         * 有并发参与的情况下当前线程在方法结束时是抛出中断异常还是重新中断线程以保留中断状态。而如果没有被中断
         * 则重新循环。
         * ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所有[
         * 状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状态]期
         * 间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:重中断),
         * 意味着在整体流程结束后需要重新线程中断以保持中断状态。
         * ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独占
         * 节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所移除,
         * 因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null同时也意
         * 味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样的节点虽然不
         * 是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断唤醒的情况,独占
         * 节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。
         * ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断,最
         * 后返回剩余的等待时间戳。
         */
        @Override
        public final long awaitNanos(long nanosTimeout) throws InterruptedException {
            // ---- 方法首先会判断当前线程是否被中断,是则直接抛出中断异常免,否则将当前线程封装为[等待状态]为
            // CONDITION(-2:条件)的独占节点尾插至条件队列中。
            if (Thread.interrupted())
                throw new InterruptedException();
            Node node = addConditionWaiter();
            // ---- 随后当前线程会以独占模式释放当前持有的所有[状态],该行为意味着其解除了对AQS的独占,因此从此处
            // 开始将由线程并发的竞争获取[状态]。
            int savedState = fullyRelease(node);
            // ---- 计算方法的等待截止时间戳,随后进入判断独占节点是否位于同步队列的循环。在循环中,当前线程首先会
            // 判断等待时间是否超时,是则强制插入至同步队列中并结束循环;否则判断剩余的等待时间是否 >= 自旋阈值。
            // 是则进入令自身进入进入有限等待状态;否则继续执行循环。因为如果等待时间非常短的话等待就是不值得的,
            // 因为Java线程状态的转换也是一件相当耗时耗力的行为,还不如直接自旋等待。
            // ---- 当前线程因为信号/中断/超时等待原因后,会判断自身时因为信号/超时而唤醒还是因为中断而唤醒,已决
            // 定在有并发参与的情况下当前线程在方法结束时是抛出中断异常还是重新中断线程以保留中断状态。而如果没有
            // 被中断则重新循环。
            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();
            }

            // ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所
            // 有[状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状
            // 态]期间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:
            // 重中断),意味着在整体流程结束后需要重新线程中断以保持中断状态。
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            // ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独
            // 占节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所
            // 移除,因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null
            // 同时也意味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样
            // 的节点虽然不是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断
            // 唤醒的情况,独占节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            // ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断,
            // 最后返回剩余的等待时间戳。
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return deadline - System.nanoTime();
        }

        /**
         * Implements absolute timed condition wait.
         * 实现绝对的定时等待。
         * <ol>
         * <li> If current thread is interrupted, throw InterruptedException.
         * 如果当前线程被中断,抛出中断异常。
         * <li> Save lock state returned by {@link #getState}.
         * 保存通过getState()方法返回的锁状态。
         * <li> Invoke {@link #release} with saved state as argument, throwing IllegalMonitorStateException if it fails.
         * 将保存的锁状态作为参数调用release()方法,如果失败抛出非法监视状态异常。
         * <li> Block until signalled, interrupted, or timed out.
         * 阻塞直至收到信号,中断,或超时。
         * <li> Reacquire by invoking specialized version of {@link #acquire} with saved state as argument.
         * 通过将保存的锁状态作为参数调用指定的acquire()方法版本获取状态。
         * <li> If interrupted while blocked in step 4, throw InterruptedException.
         * 如果在步骤四阻塞期间被中断,抛出中断异常。
         * <li> If timed out while blocked in step 4, return false, else true.
         * 如果在步骤四等待超时,返回false;否则返回true。
         * </ol>
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 等待直至
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 令当前线程以独占模式释放所有的状态后在当前条件对象中有限等待,直至因为信号/中断/超时而被唤醒并重新获
         * 取之前释放的所有状态并返回是否超时,true表示是;false表示否。在成功获取状态后,如果存在中断并发的情况
         * 下,如果当前线程因为信号而唤醒则需要保留中断状态;否则抛出中断异常。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法首先计算截止时间戳,随后判断当前线程是否已被中断,是则直接抛出中断;否则将当前线程封装为[等待
         * 状态]为CONDITION(-2:条件)的独占节点尾插至条件队列中。
         * ---- 随后当前线程会以独占模式一次性释放所有[状态],并进入判断独占节点是否位于同步队列的循环中。循环首先
         * 会判断当前时间是否超时,是则将独占节点尾插至同步队列中并结束循环;否则令当前线程进入有限等待状态,直
         * 至因为信号/中断/超时而被唤醒。被唤醒的当前线程会检查自身是否是因为中断而被唤醒,以决定在有中断并发的
         * 情况下是抛出中断异常还是还原中断状态。而如果没有中断并发,则方法会再次进入循环中。
         * ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所有[
         * 状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状态]期
         * 间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:重中断),
         * 意味着在整体流程结束后需要重新线程中断以保持中断状态。
         * ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所有[
         * 状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状态]期
         * 间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:重中断),
         * 意味着在整体流程结束后需要重新线程中断以保持中断状态。
         * ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独占
         * 节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所移除,
         * 因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null同时也意
         * 味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样的节点虽然不
         * 是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断唤醒的情况,独占
         * 节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。
         * ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断,
         * 最后返回剩余的等待时间戳。
         */
        @Override
        public final boolean awaitUntil(Date deadline) throws InterruptedException {
            // ---- 方法首先计算截止时间戳,随后判断当前线程是否已被中断,是则直接抛出中断;否则将当前线程封装为[等
            // 待状态]为CONDITION(-2:条件)的独占节点尾插至条件队列中。
            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;
            }
            // ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所
            // 有[状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状
            // 态]期间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:
            // 重中断),意味着在整体流程结束后需要重新线程中断以保持中断状态。
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            // ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独
            // 占节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所
            // 移除,因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null
            // 同时也意味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样
            // 的节点虽然不是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断
            // 唤醒的情况,独占节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            // ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断,
            // 最后返回是否超时。
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return !timedout;
        }

        /**
         * Implements timed condition wait.
         * 实现定时等待
         * <ol>
         * <li> If current thread is interrupted, throw InterruptedException.
         * 如果当前线程被中断,抛出中断异常。
         * <li> Save lock state returned by {@link #getState}.
         * 保存通过getState()方法返回的锁状态。
         * <li> Invoke {@link #release} with saved state as argument, throwing IllegalMonitorStateException if it fails.
         * 将保存的锁状态作为参数调用release()方法,如果失败抛出非法监视状态异常。
         * <li> Block until signalled, interrupted, or timed out.
         * 阻塞直至收到信号,中断,或超时。
         * <li> Reacquire by invoking specialized version of {@link #acquire} with saved state as argument.
         * 通过将保存的锁状态作为参数调用指定的acquire()方法版本获取状态。
         * <li> If interrupted while blocked in step 4, throw InterruptedException.
         * 如果在步骤四阻塞期间被中断,抛出中断异常。
         * <li> If timed out while blocked in step 4, return false, else true.
         * 如果在步骤四等待超时,返回false;否则返回true。
         * </ol>
         *
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 等待
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 令当前线程以独占模式释放所有的状态后在当前条件对象中有限等待,直至因为信号/中断/超时而被唤醒并重新获
         * 取之前释放的所有状态并返回是否超时,true表示是;false表示否。在成功获取状态后,如果存在中断并发的情况
         * 下,如果当前线程因为信号而唤醒则需要保留中断状态;否则抛出中断异常。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法首先计算截止时间戳,随后判断当前线程是否已被中断,是则直接抛出中断;否则将当前线程封装为[等待
         * 状态]为CONDITION(-2:条件)的独占节点尾插至条件队列中。
         * ---- 随后当前线程会以独占模式一次性释放所有[状态],并进入判断独占节点是否位于同步队列的循环中。循环首先
         * 会判断当前时间是否超时,是则将独占节点尾插至同步队列中并结束循环;否则令当前线程进入有限等待状态,直
         * 至因为信号/中断/超时而被唤醒。被唤醒的当前线程会检查自身是否是因为中断而被唤醒,以决定在有中断并发的
         * 情况下是抛出中断异常还是还原中断状态。而如果没有中断并发,则方法会再次进入循环中。
         * ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所有[
         * 状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状态]期
         * 间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:重中断),
         * 意味着在整体流程结束后需要重新线程中断以保持中断状态。
         * ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所有[
         * 状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状态]期
         * 间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:重中断),
         * 意味着在整体流程结束后需要重新线程中断以保持中断状态。
         * ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独占
         * 节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所移除,
         * 因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null同时也意
         * 味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样的节点虽然不
         * 是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断唤醒的情况,独占
         * 节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。
         * ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断,
         * 最后返回剩余的等待时间戳。
         */
        @Override
        public final boolean await(long time, TimeUnit unit) throws InterruptedException {
            // ---- 方法首先计算截止时间戳,随后判断当前线程是否已被中断,是则直接抛出中断;否则将当前线程封装为[等
            // 待状态]为CONDITION(-2:条件)的独占节点尾插至条件队列中。
            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();
            }
            // ---- 当前线程被唤醒并被迁移至同步队列后,当前线程会参与对[状态]的获取,并且会一次性获得之前释放的所
            // 有[状态]。获取成功(事实上应该也不会再获取失败了,除非是OOM等非常规原因)后方法会返回线程在获取[状
            // 态]期间是否被中断,是则将之中断状态在不为THROW_IE(-1:异常)的前提下将之赋值为REINTERRUPT(1:
            // 重中断),意味着在整体流程结束后需要重新线程中断以保持中断状态。
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            // ---- 当前线程成功获取[状态]后会继续判断独占节点的[后继等待者]是否不为null。[后继等待者]不为null意味着独
            // 占节点本身不为[最后等待者]且并非因为中断/超时而被唤醒,并且没有及时被其它AQS独占线程所触发的清理所
            // 移除,因为只有信号唤醒以及清理时才会在唤醒节点[线程]前将节点的[后继等待者]置null。[后继等待者]不为null
            // 同时也意味着虽然当前线程已经位于同步队列中并且已经成功获取了[状态],但其依然还位于条件队列中,这样
            // 的节点虽然不是取消节点,但实际上本质却与取消节点相同,因此会触发清理。而对于为[最后等待者]但被中断
            // 唤醒的情况,独占节点的清理会在新节点入队时发生。因为对于这种情况线程无法判断节点是否位于条件队列中。
            if (node.nextWaiter != null)
                unlinkCancelledWaiters();
            // ---- [状态]获取,取消节点清理都结束,方法会判断中断状态是否为不为0,是则需要抛出异常或重新将线程中断,
            // 最后返回是否超时。
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
            return !timedout;
        }

        // support for instrumentation
        // 为仪表化支持

        /**
         * Returns true if this condition was created by the given synchronization object.
         * 如果当前条件对象通过指定同步对象创建则返回true。
         *
         * @return {@code true} if owned 如果有用则为true
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 是否被拥有
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 判断当前条件对象是否由指定同步对象创建,是则返回true;否则返回false。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法会将指定同步对象与当前同步对象做对比,相同则返回true;否则返回false。
         */
        final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
            return sync == AbstractQueuedSynchronizer.this;
        }

        /**
         * Queries whether any threads are waiting on this condition. Implements
         * {@link AbstractQueuedSynchronizer#hasWaiters(ConditionObject)}.
         * 查询是否由线程在当前条件中等待。实现AbstractQueuedSynchronizer#hasWaiters(ConditionObject)。
         *
         * @return {@code true} if there are any waiting threads  如果有任意等待线程则为true。
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively} returns {@code false}
         *                                      非法监视状态异常:如果isHeldExclusively()返回false。
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 是否存在等待者
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 判断当前条件对象中是否存在等待的线程,是则返回true;否则返回false。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法首先会判断当前AQS是否被独占,否则直接抛出非法监视状态异常,因为条件机制只有在独占模式下才可用。
         * 随后方法会遍历的条件队列,如果在其中发现了[等待状态]为CONDITION(-2:条件)的节点则返回true;否则在遍
         * 历结束后返回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)}.
         * 返回在当前条件中等待的线程的估计值。实现AbstractQueuedSynchronizer#getWaitQueueLength(ConditionObject)。
         *
         * @return the estimated number of waiting threads 等待线程的估计值。
         * @throws IllegalMonitorStateException if {@link #isHeldExclusively} returns {@code false}
         *                                      非法监视状态异常:如果isHeldExclusively()返回false。
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 获取等待队列长度
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 获取在当前条件对象中等待的线程的数量估计值。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法首先会判断当前AQS是否被独占,否则直接抛出非法监视状态异常,因为条件机制只有在独占模式下才可用。
         * 随后方法会遍历的条件队列,并记录[等待状态]为CONDITION(-2:条件)的独占节点总数并返回。
         */
        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}
         *                                      非法监视状态异常:如果isHeldExclusively()返回false。
         * @Description: --------------------------------------------------------- 名称 ---------------------------------------------------------
         * 获取等待线程集
         * @Description: --------------------------------------------------------- 作用 ---------------------------------------------------------
         * 获取在当前条件对象中等待的线程估计集。
         * @Description: --------------------------------------------------------- 逻辑 ---------------------------------------------------------
         * ---- 方法首先会判断当前AQS是否被独占,否则直接抛出非法监视状态异常,因为条件机制只有在独占模式下才可用。
         * 随后方法会遍历的条件队列,并保存[等待状态]为CONDITION(-2:条件)的独占节点[线程],最后以集的形式返回。
         */
        protected final Collection<Thread> getWaitingThreads() {
            if (!isHeldExclusively())
                throw new IllegalMonitorStateException();
            ArrayList<Thread> list = new ArrayList<Thread>();
            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);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

说淑人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值