staticfinalclassNode{/** Marker to indicate a node is waiting in shared mode */staticfinal Node SHARED =newNode();/** Marker to indicate a node is waiting in exclusive mode */staticfinal Node EXCLUSIVE = null;/** waitStatus value to indicate thread has cancelled */staticfinalint CANCELLED =1;/** waitStatus value to indicate successor's thread needs unparking */staticfinalint SIGNAL =-1;/** waitStatus value to indicate thread is waiting on condition */staticfinalint CONDITION =-2;/**
* waitStatus value to indicate the next acquireShared should
* unconditionally propagate
*/staticfinalint 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).
*/volatileint waitStatus;/**
* Link to predecessor node that current node/thread relies on
* for checking waitStatus. Assigned during enqueuing, and nulled
* out (for sake of GC) only upon dequeuing. Also, upon
* cancellation of a predecessor, we short-circuit while
* finding a non-cancelled one, which will always exist
* because the head node is never cancelled: A node becomes
* head only as a result of successful acquire. A
* cancelled thread never succeeds in acquiring, and a thread only
* cancels itself, not any other node.
*/volatile Node prev;/**
* Link to the successor node that the current node/thread
* unparks upon release. Assigned during enqueuing, adjusted
* when bypassing cancelled predecessors, and nulled out (for
* sake of GC) when dequeued. The enq operation does not
* assign next field of a predecessor until after attachment,
* so seeing a null next field does not necessarily mean that
* node is at end of queue. However, if a next field appears
* to be null, we can scan prev's from the tail to
* double-check. The next field of cancelled nodes is set to
* point to the node itself instead of null, to make life
* easier for isOnSyncQueue.
*/volatile Node next;/**
* The thread that enqueued this node. Initialized on
* construction and nulled out after use.
*/volatile Thread thread;/**
* Link to next node waiting on condition, or the special
* value SHARED. Because condition queues are accessed only
* when holding in exclusive mode, we just need a simple
* linked queue to hold nodes while they are waiting on
* conditions. They are then transferred to the queue to
* re-acquire. And because conditions can only be exclusive,
* we save a field by using special value to indicate shared
* mode.
*/
Node nextWaiter;/**
* Returns true if node is waiting in shared mode.
*/finalbooleanisShared(){return nextWaiter == SHARED;}/**
* Returns previous node, or throws NullPointerException if null.
* Use when predecessor cannot be null. The null check could
* be elided, but is present to help the VM.
*
* @return the predecessor of this node
*/final Node predecessor()throws NullPointerException {
Node p = prev;if(p == null)thrownewNullPointerException();elsereturn p;}Node(){// Used to establish initial head or SHARED marker}Node(Thread thread, Node mode){// Used by addWaiterthis.nextWaiter = mode;this.thread = thread;}Node(Thread thread,int waitStatus){// Used by Conditionthis.waitStatus = waitStatus;this.thread = thread;}}
返回当前节点的前一个节点,或者抛出异常
final Node predecessor()throws NullPointerException {
Node p = prev;if(p == null)thrownewNullPointerException();elsereturn p;}
构造函数
初始化头结点或者共享型标记
Node(){// Used to establish initial head or SHARED marker}
等待对列使用
Node(Thread thread, Node mode){// Used by addWaiterthis.nextWaiter = mode;this.thread = thread;}
条件对列使用
Node(Thread thread,int waitStatus){// Used by Conditionthis.waitStatus = waitStatus;this.thread = thread;}
如果节点存在后继,则唤醒他
privatevoidunparkSuccessor(Node node){
如果状态为负(即(可能需要信号)在预期会发信号时尽量清除信号。
如果这个操作失败或者状态被等待的线程改变了,这是可以的。
int ws = node.waitStatus;if(ws <0)
如果waitStatus是负数,那么久需要将信号置位0compareAndSetWaitStatus(node, ws,0);
要实现unpark的线程被后继节点持有,但是如果节点对应的线程被取消或者为空,
那么从tail从后向前逆序遍历,直到第一个没有被取消的节点。
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);}
释放共享模式的动作,通知后续节点并保证传播
privatevoiddoReleaseShared(){
确保一个release传播,即使有其他正在进行的acquires/releases.
如果需要通知,他会尝试unpark头结点的后继节点。
但如果不需要,status设置为PROPAGATE(自动传播)去确保release,传播的继续。
此外,我们需要进入自旋来防止执行此操作时添加新的节点。
此外,与unpark后继节点的其他用法不同,我们需要知道如果CAS重置状态失败,是否需要重新检查。
自旋
for(;;){
Node h = head;
头结点不为空,也不是尾节点
if(h != null && h != tail){int ws = h.waitStatus;if(ws == Node.SIGNAL){
如果CAS操作无法执行,那么循环
if(!compareAndSetWaitStatus(h, Node.SIGNAL,0))continue;// loop to recheck cases
如果waitStatus等于-1(指示后继节点需要释放),并且CAS操作成功
那么unpark后继节点。
unparkSuccessor(h);}elseif(ws ==0&&!compareAndSetWaitStatus(h,0, Node.PROPAGATE))continue;// loop on failed CAS}if(h == head)// loop if head changedbreak;}}
设置队列头,并检查后继节点是否是SHARED状态在等待
如果,是SHARED则向后传播
如果不是,设置waitStatus状态为PROPAGATE或者propagate >0
propagate:从tryacquired返回的值
privatevoidsetHeadAndPropagate(Node node,int propagate){
Node h = head;// Record old head for check belowsetHead(node);
尝试唤醒队列中的下一个节点:
传播由调用者指示,
或者被先前的操作记录
(注意:这会使用waitStatus的签名,因为PROPAGATE 可以转换成SIGNAL)
并且
下一个节点以共享模式等待,
或者我们不知道,因为它看起来是空的
但是只要有多个竞争 acquires/releases(大多数需要尽快唤醒的情况下)
这两种检查的保守性可能会导致不必要的唤醒,/*
* Try to signal next queued node if:
* Propagation was indicated by caller,
* or was recorded (as h.waitStatus either before
* or after setHead) by a previous operation
* (note: this uses sign-check of waitStatus because
* PROPAGATE status may transition to SIGNAL.)
* and
* The next node is waiting in shared mode,
* or we don't know, because it appears null
*
* The conservatism in both of these checks may cause
* unnecessary wake-ups, but only when there are multiple
* racing acquires/releases, so most need signals now or soon
* anyway.
*/if(propagate >0|| h == null || h.waitStatus <0||(h = head)== null || h.waitStatus <0){
Node s = node.next;if(s == null || s.isShared())doReleaseShared();}}
各种版本的acquire
取消正在进行的获取尝试
privatevoidcancelAcquire(Node node){
如果node不存在,那么直接return。
// Ignore if node doesn't existif(node == null)return;
将node所在的线程置为空。
node.thread = null;
跳过已经取消的前驱节点
// Skip cancelled predecessors
Node pred = node.prev;
waitStatus的值为1时,这个node标记为cancel
while(pred.waitStatus >0)
这里执行的操作就是链表的删除中间节点。
node.prev = pred = pred.prev;// predNext is the apparent node to unsplice. CASes below will// fail if not, in which case, we lost race vs another cancel// or signal, so no further action is necessary.
pred节点的next需要重新定位。
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.
将当前节点重新将状态定义为CANELLLED
node.waitStatus = Node.CANCELLED;
如果这个当前需要取消尝试获取的节点是尾节点,就需要直接remove当前节点。
// If we are the tail, remove ourselves.if(node == tail &&compareAndSetTail(node, pred)){|pred|---->|node|,如果pred的next和null相同则执行CAS操作。
compareAndSetNext(pred, predNext, null);}else{
如果当前节点的后继节点需要信号,尝试pred的next节点获得信号。否走唤醒将会传递 。
// If successor needs signal, try to set pred's next-link// so it will get one. Otherwise wake it up to propagate.int ws;if(pred != head &&((ws = pred.waitStatus)== Node.SIGNAL ||(ws <=0&&compareAndSetWaitStatus(pred, ws, Node.SIGNAL)))&&
pred.thread != null){
Node next = node.next;if(next != null && next.waitStatus <=0)compareAndSetNext(pred, predNext, next);}else{unparkSuccessor(node);}
node.next = node;// help GC}}
检查和更新未能获取的节点的状态
如果线程应该阻塞,返回true。
在所有的acquire循环中,这是最主要的信号控制。
需要 pred == node.prev
privatestaticbooleanshouldParkAfterFailedAcquire(Node pred, Node node){int ws = pred.waitStatus;if(ws == Node.SIGNAL)/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/returntrue;if(ws >0){/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/do{
node.prev = pred = pred.prev;}while(pred.waitStatus >0);
pred.next = node;}else{/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/compareAndSetWaitStatus(pred, ws, Node.SIGNAL);}returnfalse;}
查询是否有线程等待获取的时间大于当前线程。
此方法调用等价于(可能比等价方法更高效):
getFirstQueuedThread()!= Thread.currentThread()&&hasQueuedThreads()
注意,由于中断和超时导致的取消可能随时发生, true返回不能保证其他线程将在当前线程之前获得。
同样,由于队列为空,在此方法返回false后,其他线程也可能在排队竞赛中获胜。
此方法被设计为由一个公平的同步器使用,以避免冲突。
这种同步器的tryAcquire方法应该返回 false,如果该方法返回true(除非是可重入获取),
那么它的 tryacquiresred方法应该返回一个负值。
如果当前线程之前有一个排队的线程,则为true;
如果当前线程位于队列的头部或队列为空,则为false。
publicfinalbooleanhasQueuedPredecessors(){
这个正确性依赖于:头结点在尾结点之前初始化;
如果当前线程是第一个入队的,那么头结点的下一个节点必须是精确的。
tail以相反的初始化顺序读取字段。
Node t = tail;// Read fields in reverse initialization order
Node h = head;
Node s;return h != t &&((s = h.next)== null || s.thread != Thread.currentThread());}
仪器工具和监视方法
返回 等待require方法的线程的数量的估计值。
这个数量是估计值,是因为线程数量是会一直处在一个动态变化的状态。
这个方法用来监视系统状态,不作为同步控制。
publicfinalintgetQueueLength(){int n =0;for(Node p = tail; p != null; p = p.prev){if(p.thread != null)++n;}return n;}
返回一个集合——等待require方法的线程的集合。
由于确切的线程在我们构造这一集合时可能动态的在变化,所以这个结果只能是最优估计。
集合中的元素排序不分先后。
这种方法旨在促进子类的构建,从而提供更广泛的监控工具。
publicfinal Collection<Thread>getQueuedThreads(){
ArrayList<Thread> list =newArrayList<Thread>();for(Node p = tail; p != null; p = p.prev){
Thread t = p.thread;if(t != null)
list.add(t);}return list;}
返回一个集合——等待require方法的线程(独占式)的集合
publicfinal Collection<Thread>getExclusiveQueuedThreads(){
ArrayList<Thread> list =newArrayList<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;}
返回一个集合——等待require方法的线程(共享式)的集合
publicfinal Collection<Thread>getSharedQueuedThreads(){
ArrayList<Thread> list =newArrayList<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;}
返回一个字符串:识别这个同步器以及他的状态状态。
public String toString(){int s =getState();
String q =hasQueuedThreads()?"non":"";returnsuper.toString()+"[State = "+ s +", "+ q +"empty queue]";}
支持Condition的内部方法
返回true:如果节点(总是最初放置在条件队列中的节点)在同步队列中等待二次acquire
finalbooleanisOnSyncQueue(Node node){if(node.waitStatus == Node.CONDITION || node.prev == null)returnfalse;if(node.next != null)// If has successor, it must be on queuereturntrue;
节点node.prev可以确保非空,但是不会马上出现在队列上,这是因为CAS放置节点的操作可能失败。
所以我们必须从尾部开始遍历,确保CAS操作成功。
在对这个方法的调用中,它总是在尾部附近,除非CAS失败(这是不可能的),否则它就会在那里,
所以我们几乎不怎么遍历。
returnfindNodeFromTail(node);}
如果从尾部遍历同步队列,发现节点node存在,则返回true。
只有isOnSyncQueue(Node node)方法需要的时候调用。
privatebooleanfindNodeFromTail(Node node){
Node t = tail;
自旋操作,直到完成为止。
for(;;){if(t == node)returntrue;if(t == null)returnfalse;
t = t.prev;}}
如果这个condition是由给定的同步对象创建的,则返回true。
/**
* @return {@code true} if owned
*/finalbooleanisOwnedBy(AbstractQueuedSynchronizer sync){return sync == AbstractQueuedSynchronizer.this;}
查询是否有线程等待此条件。
实现: publicfinalbooleanhasWaiters(ConditionObject condition) 方法
protectedfinalbooleanhasWaiters(){if(!isHeldExclusively())thrownewIllegalMonitorStateException();for(Node w = firstWaiter; w != null; w = w.nextWaiter){if(w.waitStatus == Node.CONDITION)returntrue;}returnfalse;}
返回等待此条件的线程数的估计数。
实现:publicfinalintgetWaitQueueLength(ConditionObject condition)方法
protectedfinalintgetWaitQueueLength(){if(!isHeldExclusively())thrownewIllegalMonitorStateException();int n =0;for(Node w = firstWaiter; w != null; w = w.nextWaiter){if(w.waitStatus == Node.CONDITION)++n;}return n;}
返回一个集合,其中包含可能正在等待此条件的线程。
实现:publicfinal Collection<Thread>getWaitingThreads(ConditionObject condition)方法
protectedfinal Collection<Thread>getWaitingThreads(){if(!isHeldExclusively())thrownewIllegalMonitorStateException();
ArrayList<Thread> list =newArrayList<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;}}
CAS
/**
* 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).
*/privatestaticfinal Unsafe unsafe = Unsafe.getUnsafe();privatestaticfinallong stateOffset;privatestaticfinallong headOffset;privatestaticfinallong tailOffset;privatestaticfinallong waitStatusOffset;privatestaticfinallong 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){thrownewError(ex);}}/**
* CAS head field. Used only by enq.
*/privatefinalbooleancompareAndSetHead(Node update){return unsafe.compareAndSwapObject(this, headOffset, null, update);}/**
* CAS tail field. Used only by enq.
*/privatefinalbooleancompareAndSetTail(Node expect, Node update){return unsafe.compareAndSwapObject(this, tailOffset, expect, update);}/**
* CAS waitStatus field of a node.
*/privatestaticfinalbooleancompareAndSetWaitStatus(Node node,int expect,int update){return unsafe.compareAndSwapInt(node, waitStatusOffset,
expect, update);}/**
* CAS next field of a node.
*/privatestaticfinalbooleancompareAndSetNext(Node node,
Node expect,
Node update){return unsafe.compareAndSwapObject(node, nextOffset, expect, update);}