AbstractQueuedSynchronizer(AQS)类 注释翻译

AQS注释翻译

1. 同步器概述

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 tobe 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.

本类提供了一个用于实现阻塞锁和同步器(信号量、事件等)的框架,该框架依赖先进先出 (FIFO) 的等待队列来实现。它为大多数通过单个int类型的原子值来表示状态的同步器提供了实现基础。子类必须重写更改同步器状态的protected方法,并定义该状态在获取或释放子类对象方面的具体含义。基于此,此类中的其他方法实现所有排队和阻塞机制。子类可以维护其他状态字段,但就同步而言,只有使用了方法 #getState、 #setState 和 #compareAndSetState 操作以原子方式更新的int值才能够被跟踪。

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.

子类应定义为非公共内部辅助类,用于实现其外部类的同步属性。 {@code AbstractQueuedSynchronizer} 类没有实现任何同步接口。相反,它定义了诸如 {@link #acquireInterruptably} 之类的方法,这些方法可以由具体锁和相关同步器适当调用以实现它们的公共方法。

This class supports either or both a default exclusive mode and a shared mode. When acquired in exclusive mode, attempted acquires by other threads cannot succeed. Shared mode acquires by multiple threads may (but need not) succeed. This class does not understand these differences except in the mechanical sense that when a shared mode acquire succeeds, the next waiting thread (if one exists) must also determine whether it can acquire as well. Threads waiting in the different modes share the same FIFO queue. Usually, implementation subclasses support only one of these modes, but both can come into play for example in a {@link ReadWriteLock}. Subclasses that support only exclusive or only shared modes need not define the methods supporting the unused mode.

此类默认支持独占模式和共享模式获取同步状态。当以独占模式获取同步状态时,其他线程尝试获取不会成功。共享模式下,多个线程获取同步状态一般(但不一定)会成功。这个类会忽略这两种模式在机制上的差异,那就是当线程在共享模式下成功获取到同步状态时,下一个等待的线程(如果存在)也必须确定它是否也可以获取该状态。

This class defines a nested {@link ConditionObject} class that can be used as a {@link Condition} implementation by subclasses supporting exclusive mode for which method {@link#isHeldExclusively} reports whether synchronization is exclusively held with respect to the current thread, method {@link #release} invoked with the current {@link#getState} value fully releases this object, and {@link #acquire}, given this saved state value, eventually restores this object to its previous acquired state.
No {@code AbstractQueuedSynchronizer} method otherwise creates such a condition, so if this constraint cannot be met, do not use it.
The behavior of {@link ConditionObject} depends of course on the semantics of its synchronizer implementation.

AQS定义了一个内部类ConditionObject,可以当做Condition的实例供支持独占模式的子类使用。在独占模式下,方法 #isHeldExclusively用于表示当前线程是否在独占子类对象,以方法#getState的返回值为入参,调用方法#release可以完全释放子类对象。使用这个值调用#acquire方法, 最终恢复到前一个获取锁的状态。否则,没有AbstractQueuedSynchronizer中没有其它方法创造这个条件, 所以如果不能满足这个约束,就不要使用它。内部类 ConditionObject的行为当然取决于它的同步器实现的语义。

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.

该类提供内部队列的检查、检测和监视方法,以及condition对象的类似方法。自定义同步组件使用AbstractQueuedSynchronizer同步器实现其同步机制,可以根据需要使用AQS的这些方法。

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 方法,该方法在反序列化时将其恢复到已知的初始状态。

2. 同步器用法

To use this class as the basis of a synchronizer, redefine the following methods, as applicable, by inspecting and/or modifying the synchronization state using {@link #getState}, {@link#setState} and/or {@link #compareAndSetState}:

  • {@link #tryAcquire}
  • {@link #tryRelease}
  • {@link #tryAcquireShared}
  • {@link #tryReleaseShared}
  • {@link #isHeldExclusively}

要使用此类作为同步器的基础,以便使用 #getState方法获取同步状态,使用#setState 或 #compareAndSetState方法 设置同步状态,请重新定义以下方法(如适用):

  • #tryAcquire
  • #tryRelease
  • #tryAcquireShared
  • #tryReleaseShared
  • #isHeldExclusively

Each of these methods by default throws {@link UnsupportedOperationException}. Implementations of these methods must be internally thread-safe, and should in general be short and not block. Defining these methods is the only supported means of using this class. All other methods are declared {@code final} because they cannot be independently varied.

默认情况下,这些方法中的每一个都会抛出UnsupportedOperationException异常。这些方法的实现必须是内部线程安全的,并且通常应该是简短且无锁的。重写这些方法是能够使用此类的唯一方式。所有其他方法都声明为 final,因为它们不能独立变化。

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.

您也能看到本类从抽象类AbstractOwnableSynchronizer继承的方法,用于跟踪独占了同步器的线程。建议您使用它们——它们开启了监视和诊断功能,可以帮助用户确定哪些线程持有锁。

Even though this class is based on an internal FIFO queue, it does not automatically enforce FIFO acquisition policies. The core of exclusive synchronization takes the form:
Acquire:
while (!tryAcquire(arg)) {
enqueue thread if it is not already queued;
possibly block current thread;
}
Release:
if (tryRelease(arg))
unblock the first queued thread;
(Shared mode is similar but may involve cascading signals.)

即使这个类基于内部FIFO队列,它也不会自动执行FIFO获取策略。独占式同步的核心是:

Acquire: // 获取同步状态
    while (!tryAcquire(arg)) {  // 若线程获取同步状态失败,进入同步队列
       <em> enqueue thread if it is not already queued <em>; // 如果线程还没有排队,则排队
       <em> possibly block current thread </em>; // 可能阻塞当前线程
    }
Release: // 释放同步状态
    if (tryRelease(arg))  // 线程尝试释放同步状态
       <em>unblock the first queued thread</em>;  // 若释放成功,唤醒阻塞在队列的第一个线程
(Shared mode is similar but may involve cascading signals.) // 共享模式与此类似,但可能涉及级联信号

Because checks in acquire are invoked before enqueuing, a newly acquiring thread may barge ahead of others that are blocked and queued.
However, you can, if desired, define {@code tryAcquire} and/or {@codetryAcquireShared} to disable barging by internally invoking one or more of the inspection methods, thereby providing a fair FIFO acquisition order.
In particular, most fair synchronizers can define {@code tryAcquire} to return {@code false} if {@link #hasQueuedPredecessors} (a method specifically designed to be used by fair synchronizers) returns {@code true}. Other variations are possible.

因为对获取同步状态的检查是在入队之前进行, 所以一个新线程可能会插入到其他被阻塞和入队的线程之前。
但是,如果需要,您可以定义 #tryAcquire和/或 #ryAcquireShared方法以通过内部调用一种或多种检查方法来禁用非公平性地入队,从而提供一个公平的 FIFO顺序。
特别是,大多数公平同步器可以重写方法#tryAcquire以返回false来保证线程公平地获取同步状态,如果方法#hasQueuedPredecessors(一种专门设计用于公平同步器的方法)返回true。 其它的变化也是可能的。

Throughput and scalability are generally highest for the default barging (also known as greedy, renouncement, and convoy-avoidance) strategy.
While this is not guaranteed to be fair or starvation-free, earlier queued threads are allowed to recontend before later queued threads, and each recontention has an unbiased chance to succeed against incoming threads.
Also, while acquires do not spin in the usual sense, they may perform multiple invocations of {@code tryAcquire} interspersed with other computations before blocking.
This gives most of the benefits of spins when exclusive synchronization is only briefly held, without most of the liabilities when it isn’t.
If so desired, you can augment this by preceding calls to acquire methods with “fast-path” checks, possibly prechecking {@link #hasContended} and/or {@link #hasQueuedThreads} to only do so if the synchronizer is likely not to be contended.

对于默认的插队策略(也叫greedy/renouncement/convoy-avoidance), 吞吐量和可伸缩性通常最高。
尽管这不能保证公平性, 但允许早入队的线程在后入队的线程之前重新竞争, 每个重新竞争的线程拥有公平的机会打败新来的线程。
此外,获取同步状态通常不会自旋, 但线程在被阻塞之前, 伴随着其他计算过程, 可能会多次调用 #tryAcquire方法。
当独占同步器只是短暂的被线程持有时, 这对于自旋来说大有裨益, 而当它没有被持有时,系统也没有多余的性能损耗。
如果需要,您可以通过前面的调用来获取带有“fast-path”检查的方法来增强这一点,如果同步器可能没有被争夺, 或许只会预先检查 #hasContended方法和 #hasQueuedThreads方法。

This class provides an efficient and scalable basis for synchronization in part by specializing its range of use to synchronizers that can rely on {@code int} state, acquire, and release parameters, and an internal FIFO wait queue.
When this does not suffice, you can build synchronizers from a lower level using {@link java.util.concurrent.atomic atomic} classes, your own custom {@link java.util.Queue} classes, and {@link LockSupport} blocking support.

此类通过将其使用范围专门用于 可以依赖于同步状态state的整型值,获取和释放同步状态以及内部 FIFO 等待队列的同步器,为同步提供了高效且可扩展的基础。当这些不能满足你的需要时, 你可以使用原子类、 你自己定义的队列类,以及支持阻塞的LockSupport 类来实现你想要的同步效果。

3. 用法示例

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:

这是一个不可重入的互斥锁类,它使用值0表示未锁定状态,用值1表示锁定状态。
虽然不可重入锁并不严格要求记录当前所有者线程,但这个类还是这样做了,目的是为了更容易监控使用情况。
它还支持conditions,并公开了其中一种检测方法:

// 自定义同步组件                                               
class Mutex implements Lock, java.io.Serializable {                                                                       
  // Our internal helper class 咱的内部辅助类Sync同步器,继承AQS,重写相关方法,以实现外部类的同步功能                         
  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) {                       
      assert acquires == 1; // Otherwise unused                     
      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; // Otherwise unused                     
      if (getState() == 0) throw new IllegalMonitorStateException();
      setExclusiveOwnerThread(null);                                
      setState(0);                                                  
      return true;                                                  
    }                                                               
                                                                    
    // Provides a Condition  提供一个Condition                                       
    Condition newCondition() { return new ConditionObject(); }      
                                                                    
    // Deserializes properly  正确地反序列化                               
    private void readObject(ObjectInputStream s)                    
        throws IOException, ClassNotFoundException {                
      s.defaultReadObject();                                        
      setState(0); // reset to unlocked state  重置同步状态到未锁定状态            
    }                                                               
  }           
  // The sync object does all the hard work. We just forward to it. 同步对象完成所有繁重的工作。 我们只是向前看
  private final Sync sync = new Sync();                                 
                                                                        
  public void lock()                { sync.acquire(1); }                
  public boolean tryLock()          { return sync.tryAcquire(1); }      
  public void unlock()              { sync.release(1); }                
  public Condition newCondition()   { return sync.newCondition(); }     
  public boolean isLocked()         { return sync.isHeldExclusively(); }
  public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } 
  public void lockInterruptibly() throws InterruptedException {         
    sync.acquireInterruptibly(1);                                       
  }                                                                     
  public boolean tryLock(long timeout, TimeUnit unit)                   
      throws InterruptedException {                                     
    return sync.tryAcquireNanos(1, unit.toNanos(timeout));              
  }                                                                     
}}   

Here is a latch class that is like a{@link java.util.concurrent.CountDownLatch CountDownLatch} except that it only requires a single {@code signal} to fire. Because a latch is non-exclusive, it uses the {@code shared} acquire and release methods.

这是一个latch类,功能类似CountDownLatch。除此之外,它只需要一个signal来触发。 由于latch锁是非独占式的,因此它使用后缀为shared的方法来获取和释放同步状态。

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);                                  
  }                                                                      
}}

NODE节点注释翻译

1. NODE概述

Wait queue node class.

等待队列节点类

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

等待队列是“CLH”(Craig、Landin和Hagersten)锁队列的变体。CLH锁通常用于自旋锁。相反,我们将它们用于阻塞同步器,但使用相同的基本策略,即在线程的前驱节点中保存有关线程的一些控制信息。每个节点中的“status”字段跟踪线程是否应该阻塞。当一个节点的前一个节点释放时,它就会收到信号。另外,队列的每个节点充当一个特定通知样式的监视器,它持有一个等待线程。“status”字段不能控制线程是否被授予锁等。如果一个线程是队列中的第一个线程,那么它可以尝试获取锁。但是第一个并不能保证成功;它只给了你获取锁的权利。因此,当前发布的竞争者线程可能需要重新等待。

To enqueue into a CLH lock, you atomically splice it in as new

tail. To dequeue, you just set the head field.

      +------+  prev +-----+       +-----+

 head |      | <---- |     | <---- |     |  tail

      +------+       +-----+       +-----+
 

要排队进入一个CLH形式的等待队列,您可以原子地将新的节点插入队列尾部,作为新的尾部节点。要退出队列,只需设置队列头部字段。

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队列只需要对“tail”进行一次原子操作,因此存在一个简单的原子分界点,即从未入队到已入队。类似地,出队只涉及更新“head”。但是,节点需要更多的工作来确定下一个头结点是哪一个,部分原因是为了处理可能由于超时和中断而导致的取消。

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/)

节点的前驱指针"prev"(未在原始 CLH 锁中使用)主要用于处理取消等待锁的线程。 如果一个节点取消等待锁,此节点的后继节点(通常)的前驱指针会指向此节点的前驱节点。有关在自旋锁情况下类似机制的解释,请参阅 Scott 和 Scherer 的论文,网址为 http://www.cs.rochester.edu/u/scott/synchronization/

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

我们也使用“next”指针去实现阻塞机制。每个节点的线程id都保存在它自己的节点中,因此前驱节点通过遍历next节点来唤醒后继节点,以确定它是哪个线程。确定后继节点必须避免与新入队的节点竞争,以设置其前一个节点的“next”指针。当一个节点的next指针显示为空时,通过从原子更新的“tail”向后检查来解决这个问题。(换句话说,next指针是一个优化手段,因此我们通常不需要反向扫描。)

Cancellation introduces some conservatism to the basic algorithms. Since we must poll for cancellation of other nodes, we can miss noticing whether a cancelled node is ahead or behind us. This is dealt with by always unparking successors upon cancellation, allowing them to stabilize on a new predecessor, unless we can identify an uncancelled predecessor who will carry this responsibility.

为取消等待锁的线程,引入了一些保守的基本算法。 由于我们必须轮询其他节点的取消,因此我们可能无法注意到被取消的节点是前驱节点还是后继节点。除非我们能确定一个未取消的前驱节点能够承担这些工作,否则,在取消时总是解除后继节点,并为其指定新的前驱节点。

CLH queues need a dummy header node to get started. But we don't create them on construction, because it would be wasted effort if there is never contention. Instead, the node is constructed and head and tail pointers are set upon first contention.

CLH 队列需要一个虚拟的头节点作为起始节点。 但是我们不会在构造函数中创建它,因为如果没有线程竞争锁,那将是浪费精力。 相反,当有第一个竞争者时,我们才构造节点并设置头指针和尾指针。

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.

等待在condition上的线程使用相同的节点,但是使用额外的链接。只需要在简单的(非并发的)链接队列中链接节点,因为它们仅在被独占时才被访问。在等待时,一个节点被插入到条件队列中。收到信号后,节点被转移到主队列。status字段的一个特殊值用于标记节点在哪个队列上。

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.

感谢各位JSR-166规范的成员,对此类设计的批评与建议。

2. NODE用法

static final class Node {
      /** Marker to indicate a node is waiting in shared mode */
      static final Node SHARED = new Node(); // 标记节点为共享模式
      /** Marker to indicate a node is waiting in exclusive mode */
      static final Node EXCLUSIVE = null; // 标记节点为独占模式

      /** waitStatus value to indicate thread has cancelled */
      // waitStatus为CANCELLED时 表示等待锁的线程,被取消  
      static final int CANCELLED =  1; 
      /** waitStatus value to indicate successor's thread needs unparking */
      // waitStatus为SIGNAL时 表示后继线程需要被唤醒
      static final int SIGNAL    = -1;   
       // aitStatus为CONDITION时 表示线程正在等待条件
      /** waitStatus value to indicate thread is waiting on condition */
      static final int CONDITION = -2;
      /**
       * waitStatus value to indicate the next acquireShared should
       * unconditionally propagate
       */
       // 表示下一次共享模式下获取同步状态,会被无条件传播
      static final int PROPAGATE = -3; 

      /**
       * Status field, taking on only the values:
       *   SIGNAL:     The successor of this node is (or will soon be)
       *               blocked (via park), so the current node must
       *               unpark its successor when it releases or
       *               cancels. To avoid races, acquire methods must
       *               first indicate they need a signal,
       *               then retry the atomic acquire, and then,
       *               on failure, block. 
       *   CANCELLED:  This node is cancelled due to timeout or interrupt.
       *               Nodes never leave this state. In particular,
       *               a thread with cancelled node never again blocks. 
       *   CONDITION:  This node is currently on a condition queue.
       *               It will not be used as a sync queue node
       *               until transferred, at which time the status
       *               will be set to 0. (Use of this value here has
       *               nothing to do with the other uses of the
       *               field, but simplifies mechanics.) 
       *   PROPAGATE:  A releaseShared should be propagated to other
       *               nodes. This is set (for head node only) in
       *               doReleaseShared to ensure propagation
       *               continues, even if other operations have
       *               since intervened. 
       *   0:          None of the above 
       *
       * The values are arranged numerically to simplify use.
       * Non-negative values mean that a node doesn't need to
       * signal. So, most code doesn't need to check for particular
       * values, just for sign.
       *
       * The field is initialized to 0 for normal sync nodes, and
       * CONDITION for condition nodes.  It is modified using CAS
       * (or when possible, unconditional volatile writes).  
       */
       /**
        * 字段状态值,只会取以下值:
        *   SIGNAL:    当前节点的后继节点被阻塞(或将很快被阻塞),因此当前节点在释放锁或取消等待时,
        *	           必须唤醒后继节点。为了避免竞争,acquire方法必须首先表明它们需要一个信号,
        *			   然后以原子方式重试acquire,如果失败,则阻塞。
        *   CANCELLED: 由于超时或中断,该节点将被取消。节点永远不会离开这种状态。
        *			   特别是,取消节点的线程永远不会再阻塞。
        *   CONDITION: 该节点当前位于条件队列中。它在传输之前不会用作同步队列节点,
        *			   此时状态将设置为0。(此处使用此值与该字段的其他用途无关,但简化了机制.)
        *   PROPAGATE: 处于此模式下,释放共享锁具有传递性。头节点调用doReleaseShared方法,
        *			   保证传递释放共享锁,即使有其他的操作干涉。
        *   0:         节点的初始状态
        *
        *   这些值按数字排列以简化使用。非负值意味着节点不需要发出信号。 
        *   因此,大多数代码不需要检查特定值,只需检查符号。
        *
        *   对于正常同步节点,该字段初始化为0,对于条件节点,该字段初始化为CONDITION。
        *   它使用CAS(或者在可能的情况下,使用无条件的volatile写入)进行修改。
        */
      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. 
       */
       /**
        * 当前节点用prev指针代表的前驱节点检查等待状态。
        * prev指针在节点入队期间赋值,并仅在出队时赋值为null(方便GC)。
	    * 此外,取消前驱节点时,我们会使用一个短暂的循环找到一个未取消的节点,
	    * 这肯定存在,因为头节点永远不会被取消。只有成功获取到同步状态的节点,才能成为
	    * 头结点,一个被取消的线程节点永远不会成功获取到同步状态,
	    * 并且一个线程只会取消自身对应的节点,而不是任何其他节点。
        */
      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.
       */
       /**
        * 当前节点/线程释放时,next指针指向的后继节点。
        * 将非取消的前驱节点的next指针指向入队的节点,出队时,赋值为null(方便GC)。
	    * 新的节点入队后, 前驱节点的next指针才会被赋值,指向这个新节点,
	    * 因此next指针为null并不意味着该节点在队尾。
	    * 但是,如果next指针为null时,我们可以从队尾扫描prev指针做双重检查。
	    * 被取消节点的next指针被设置为指向节点本身,而不是null,以便在同步队列更容易处理。
	    */
      volatile Node next;

      /**
       * The thread that enqueued this node.  Initialized on
       * construction and nulled out after use. 
       */
       // 入队节点的线程,在节点的构造函数中初始化,使用完后被赋值为null
      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。 
        * 因为条件队列只有在独占模式下才会被访问,所以我们只需要一个简单的链接队列来保存节点,
        * 因为它们正在等待条件。 然后将它们转移到队列以重新获取。 
        * 并且因为条件只能是独占的,所以我们通过使用特殊值保存该字段以表明这是共享模式。
        */
      Node nextWaiter;

      /**
       * Returns true if node is waiting in shared mode. 
       */
       // 如果节点在共享模式下等待,在返回TRUE
      final boolean isShared() {
          return nextWaiter == SHARED;
      }

      /**
       * Returns previous node, or throws NullPointerException if null.
       * Use when predecessor cannot be null.  The null check could
       * be elided, but is present to help the VM. 
       *
       * @return the predecessor of this node 
       */
       /**
        * 返回前一个节点,如果为空则抛出 NullPointerException。
        * 当前驱节点不能为空时使用。 可以省略空检查,但存在以便帮助VM。
        */
      final Node predecessor() throws NullPointerException {
          Node p = prev;
          if (p == null)
              throw new NullPointerException();
          else
              return p;
      }
      
	  // 无参构造用于初始化头结点或者标记共享模式
      Node() {    // Used to establish initial head or SHARED marker  
      }
	
	  // 用于同步队列CLH添加节点
      Node(Thread thread, Node mode) {     // Used by addWaiter 
          this.nextWaiter = mode;
          this.thread = thread;
      }

	  // 用于条件队列
      Node(Thread thread, int waitStatus) { // Used by Condition 
          this.waitStatus = waitStatus;
          this.thread = thread;
      }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值