AbstractQueuedSynchronizer
ReentrantLock主要內部通過Sync來完成鎖的實現筛武,Sync內部是通過AQS同步器來完成這一工作的枫弟,下面來看看AQS這個抽象類屯掖。
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.
基于FIFO等待隊列為鎖和相關的同步器提供了一個基礎框架漾狼。該類用一個int值代表了鎖狀態(tài)去扣。子類必須定義方法對這個int值做操作锈津,規(guī)定int值代表鎖的獲取或釋放意義。
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
該類支持默認的獨占模式或共享模式隆箩。當獨占模式有線程獲取到鎖该贾,其他鎖無法再成功獲取鎖。共享模式可能由多個線程獲取鎖捌臊,下一個等待線程必須判斷自己是否也能獲取鎖杨蛋。不同模式的等待線程使用的是同一個FIFO隊列。通常,子類實現支持其中一種模式逞力,也可以同時使用例如ReadWriteLock曙寡。子類支持獨占模式或共享模式則不需要再去定義不使用的方法。
This class defines a nested {@link ConditionObject} class that can be used as a {@link Condition} implementation寇荧。
該類定義了一個內嵌的ConditionObjec用作Condition的實現類举庶,條件變量另外文章會介紹。
- java.util.concurrent.locks.AbstractQueuedSynchronizer.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.
等待隊列的節(jié)點類揩抡。該等待隊列是CLH鎖隊列的一個變體户侥。CLH鎖通常用于自旋鎖。這里我們用在阻塞同步器中峦嗤,相同的策略用來保存一些關于前輩節(jié)點與線程的控制信息蕊唐。“status”字段用來跟蹤每個節(jié)點的線程是否應該阻塞烁设。當前一個節(jié)點的前輩節(jié)點釋放鎖替梨,該節(jié)點會signalled。隊列中的每個節(jié)點也是一個特定的持有等待線程的通知監(jiān)視器装黑。雖然"status"字段不能控制線程是否能獲取到鎖副瀑。一個線程回去嘗試競爭鎖如果它在隊列頭部,但并不一定保證成功恋谭,也可能會失敗需要重新等待俗扇。
總的來說,同步器的實現基于一個FIFO隊列箕别,通過一個int值表示狀態(tài)铜幽,子類通過繼承實現用類似acquire和release方式來操作這個狀態(tài)。而多線程環(huán)境中對狀態(tài)操作需要保證原子性串稀,主要使用同步器提供的以下三個方法來操作:
/**
* The synchronization state.
*/
private volatile int state;
/**
* Returns the current value of synchronization state.
* This operation has memory semantics of a {@code volatile} read.
* @return current state value
*/
protected final int getState() {
return state;
}
/**
* Sets the value of synchronization state.
* This operation has memory semantics of a {@code volatile} write.
* @param newState the new state value
*/
protected final void setState(int newState) {
state = newState;
}
/**
* Atomically sets synchronization state to the given updated
* value if the current state value equals the expected value.
* This operation has memory semantics of a {@code volatile} read
* and write.
*
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful. False return indicates that the actual
* value was not equal to the expected value.
*/
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
Node是AQSFIFO同步隊列構成單元除抛,AQS中的同步隊列包括head,tail節(jié)點和state狀態(tài)母截。線程競爭獲取鎖時到忽,失敗了會構成Node加入隊列tail,而鎖的釋放都是從head開始的清寇。對于同步器維護的狀態(tài)state喘漏,多個線程對其的獲取將會產生一個鏈式的結構。下面來看一Node結構:
/** Marker to indicate a node is waiting in shared mode */
static final Node SHARED = new Node();
/** Marker to indicate a node is waiting in exclusive mode */
static final Node EXCLUSIVE = null;
/** waitStatus value to indicate thread has cancelled */
static final int CANCELLED = 1;
/** waitStatus value to indicate successor's thread needs unparking */
static final int SIGNAL = -1;
/** waitStatus value to indicate thread is waiting on condition */
static final int CONDITION = -2;
/**
* waitStatus value to indicate the next acquireShared should
* unconditionally propagate
*/
static final int PROPAGATE = -3;
/**
* Status field, taking on only the values:
* SIGNAL: The successor of this node is (or will soon be)
* blocked (via park), so the current node must
* unpark its successor when it releases or
* cancels. To avoid races, acquire methods must
* first indicate they need a signal,
* then retry the atomic acquire, and then,
* on failure, block.
* CANCELLED: This node is cancelled due to timeout or interrupt.
* Nodes never leave this state. In particular,
* a thread with cancelled node never again blocks.
* CONDITION: This node is currently on a condition queue.
* It will not be used as a sync queue node
* until transferred, at which time the status
* will be set to 0. (Use of this value here has
* nothing to do with the other uses of the
* field, but simplifies mechanics.)
* PROPAGATE: A releaseShared should be propagated to other
* nodes. This is set (for head node only) in
* doReleaseShared to ensure propagation
* continues, even if other operations have
* since intervened.
* 0: None of the above
*
* The values are arranged numerically to simplify use.
* Non-negative values mean that a node doesn't need to
* signal. So, most code doesn't need to check for particular
* values, just for sign.
*
* The field is initialized to 0 for normal sync nodes, and
* CONDITION for condition nodes. It is modified using CAS
* (or when possible, unconditional volatile writes).
*/
volatile int waitStatus;
首先是waitStatus這個字段:
- SIGNAL: 后續(xù)節(jié)點將要blocked,所以當前該節(jié)點在releases或者cancels時必須upark后續(xù)節(jié)點华烟。為了避免競爭翩迈,acquire方法必須首先確保處于signal狀態(tài),然后嘗試獲取鎖盔夜,失敗則進入block负饲。
- 該節(jié)點因為超時或被打斷而取消堤魁。
- 該節(jié)點正在一個Condition隊列中。
- 一個共享釋放狀態(tài)返十,應該繼續(xù)向后傳播妥泉。該狀態(tài)只會出現在隊列head,在doReleaseShared時保證狀態(tài)傳播繼續(xù),即使有其他操作介入干擾洞坑。
/**
* 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; //前驅節(jié)點
/**
* 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; //后繼節(jié)點
/**
* 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; //連接條件變量等待隊列的下一個節(jié)點盲链。
/**
* Returns true if node is waiting in shared mode.
*/
final boolean isShared() {
return nextWaiter == SHARED;
}
Node() { // Used to establish initial head or SHARED marker
}
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread;
}
以上是Node的結構和api。接下來看看AQS的api迟杂。
- AbstractQueuedSynchronizer #tryAcquire(int arg) : boolean
/**
* 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()}.
*
* <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.
* @throws IllegalMonitorStateException if acquiring would place this
* synchronizer in an illegal state. This exception must be
* thrown in a consistent fashion for synchronization to work
* correctly.
* @throws UnsupportedOperationException if exclusive mode is not supported
*/
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
獨占模式嘗試獲取鎖時使用刽沾。嘗試獲取前營先查詢是否允許操作state,若允許則嘗試獲取鎖,成功返回true,若獨占模式不支持獲取則這里拋出UnsupportedOperationException逢慌。
- AbstractQueuedSynchronizer# tryRelease : boolean
/**
* 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.
* @throws IllegalMonitorStateException if releasing would place this
* synchronizer in an illegal state. This exception must be
* thrown in a consistent fashion for synchronization to work
* correctly.
* @throws UnsupportedOperationException if exclusive mode is not supported
*/
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
用作獨占模式中釋放鎖時對state狀態(tài)的操作悠轩。只有當完全釋放间狂,state代表鎖的釋放時返回true(例如state==0)攻泼,此時其他線程會嘗試競爭鎖。
- AbstractQueuedSynchronizer# tryAcquireShared(int arg) : int
/**
* 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.
* @throws IllegalMonitorStateException if acquiring would place this
* synchronizer in an illegal state. This exception must be
* thrown in a consistent fashion for synchronization to work
* correctly.
* @throws UnsupportedOperationException if shared mode is not supported
*/
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
共享模式里嘗試獲取鎖鉴象。同樣在獲取鎖之前先查詢當前狀態(tài)state是否允許獲取鎖忙菠,如果獲取失敗,返回負值纺弊,線程進入隊列等待牛欢;成功獲取鎖且后面沒有后續(xù)線程等待返回0;成功獲取且有后續(xù)線程也獲取成功則返回一個正整數淆游。
- AbstractQueuedSynchronizer#tryReleaseShared : boolean
/**
* 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
* @throws IllegalMonitorStateException if releasing would place this
* synchronizer in an illegal state. This exception must be
* thrown in a consistent fashion for synchronization to work
* correctly.
* @throws UnsupportedOperationException if shared mode is not supported
*/
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
共享莫嘗試設置state值以反映一次釋放鎖操作傍睹。如果這次釋放后允許其他等待線程獲取鎖,則返回true犹菱。其他情況則返回false拾稳。
- AbstractQueuedSynchronizer# isHeldExclusively() : boolean
/**
* 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}.)
*
* <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
* @throws UnsupportedOperationException if conditions are not supported
*/
檢查排他模式下同步狀態(tài)是否被占用。
- AbstractQueuedSynchronizer# acquire(int arg) : void
/**
* Acquires in exclusive mode, ignoring interrupts. Implemented
* by invoking at least once {@link #tryAcquire},
* returning on success. Otherwise the thread is queued, possibly
* repeatedly blocking and unblocking, invoking {@link
* #tryAcquire} until success. This method can be used
* to implement method {@link Lock#lock}.
*
* @param arg the acquire argument. This value is conveyed to
* {@link #tryAcquire} but is otherwise uninterpreted and
* can represent anything you like.
*/
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
獨占模式下獲取鎖腊脱,忽略interrupt访得。
- 嘗試獲取(!tryAcquire(arg))
- 獲取失敗則加入等待隊列 (acquireQueued(addWaiter(Node.EXCLUSIVE), arg))),首先調用addWaiter將線程封裝成Node插入隊尾:
/**
* Creates and enqueues node for current thread and given mode.
*
* @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
* @return the new node
*/
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
/**
* Inserts node into queue, initializing if necessary. See picture above.
* @param node the node to insert
* @return node's predecessor
*/
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
如果成功加入隊尾則返回node節(jié)點,不成功則enq(node)自旋插入隊尾陕凹,直到成功返回node節(jié)點悍抑。然后接下來進行acquireQueued。
/**
* Acquires in exclusive uninterruptible mode for thread already in
* queue. Used by condition wait methods as well as acquire.
*
* @param node the node
* @param arg the acquire argument
* @return {@code true} if interrupted while waiting
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor(); //首先獲取前驅節(jié)點
if (p == head && tryAcquire(arg)) {//如果前驅節(jié)點是頭節(jié)點 且 再次嘗試獲取鎖成功,則當前線程已獲取鎖
setHead(node);//將當前節(jié)點設置為頭節(jié)點
p.next = null; // help GC 前驅節(jié)點出列
failed = false;
return interrupted; //方法返回是否被打斷過
}
if (shouldParkAfterFailedAcquire(p, node) && //檢查前驅節(jié)點狀態(tài),是否需要掛起當前節(jié)點
parkAndCheckInterrupt())//掛起當前節(jié)點并打斷
interrupted = true;//設置當前線程為打斷狀態(tài)
}
} finally {
if (failed)
cancelAcquire(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.
*
* @param pred node's predecessor holding status
* @param node the node
* @return {@code true} if thread should block
*/
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
return true;
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
/**
* Convenience method to park and then check if interrupted
*
* @return {@code true} if interrupted
*/
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
- 重新獲取鎖或異常掛起后檢查是否中斷過杜耙,調用selfInterrupt()搜骡。
- AbstractQueuedSynchronizer# release(int arg) : boolean
/**
* Releases in exclusive mode. Implemented by unblocking one or
* more threads if {@link #tryRelease} returns true.
* This method can be used to implement method {@link Lock#unlock}.
*
* @param arg the release argument. This value is conveyed to
* {@link #tryRelease} but is otherwise uninterpreted and
* can represent anything you like.
* @return the value returned from {@link #tryRelease}
*/
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
/**
* Wakes up node's successor, if one exists.
*
* @param node the node
*/
private void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
獨占模式釋放操作,成功取消一個或多個線程返回true佑女。
- 當前節(jié)點線程嘗試釋放鎖浆兰。
- 若釋放成功則調用uparkSuccessor喚醒后繼節(jié)點線程磕仅。
- AbstractQueuedSynchronizer# acquireShared() : void
/**
* Acquires in shared mode, ignoring interrupts. Implemented by
* first invoking at least once {@link #tryAcquireShared},
* returning on success. Otherwise the thread is queued, possibly
* repeatedly blocking and unblocking, invoking {@link
* #tryAcquireShared} until success.
*
* @param arg the acquire argument. This value is conveyed to
* {@link #tryAcquireShared} but is otherwise uninterpreted
* and can represent anything you like.
*/
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
/**
* Acquires in shared uninterruptible mode.
* @param arg the acquire argument
*/
private void doAcquireShared(int arg) {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
if (interrupted)
selfInterrupt();
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
共享模式下的獲取鎖操作,忽略interrupts簸呈。
- 獲取成功立即返回榕订。
- 獲取失敗當前線程組裝成SHARED.NODE加入隊尾。
- 自旋檢查前節(jié)點是否是頭節(jié)點蜕便,若是頭節(jié)點嘗試釋放劫恒,釋放失敗說明當前鎖仍被占用,繼續(xù)自旋轿腺,直到獲取鎖則設置自身為頭節(jié)點并waitStatus設置為可傳播狀態(tài),并檢查是否需要打斷两嘴,然后返回結束昂發(fā)。
- 若中途異常且未獲得鎖則取消節(jié)點族壳。
- AbstractQueuedSynchronizer# releaseShared(int arg) : boolean
/**
* Releases in shared mode. Implemented by unblocking one or more
* threads if {@link #tryReleaseShared} returns true.
*
* @param arg the release argument. This value is conveyed to
* {@link #tryReleaseShared} but is otherwise uninterpreted
* and can represent anything you like.
* @return the value returned from {@link #tryReleaseShared}
*/
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
/**
* Release action for shared mode -- signals successor and ensures
* propagation. (Note: For exclusive mode, release just amounts
* to calling unparkSuccessor of head if it needs signal.)
*/
private void doReleaseShared() {
/*
* Ensure that a release propagates, even if there are other
* in-progress acquires/releases. This proceeds in the usual
* way of trying to unparkSuccessor of head if it needs
* signal. But if it does not, status is set to PROPAGATE to
* ensure that upon release, propagation continues.
* Additionally, we must loop in case a new node is added
* while we are doing this. Also, unlike other uses of
* unparkSuccessor, we need to know if CAS to reset status
* fails, if so rechecking.
*/
for (;;) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue; // loop to recheck cases
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
break;
}
}
共享模式的釋放操作憔辫,unlock時使用,如果成功釋放鎖且喚醒線程則返回true仿荆。
- 嘗試釋放鎖贰您。
- 有線程成功喚醒后,繼續(xù)循環(huán)嘗試釋放后繼節(jié)點拢操。
- 若后繼節(jié)點狀態(tài)SIGNAL表明后繼節(jié)點的后繼節(jié)點需要喚醒锦亦,嘗試喚醒。
- 若后繼節(jié)點狀態(tài)0則嘗試設置為PROPAGATE令境。
- 直到頭節(jié)點改變結束循環(huán)