AQS原始碼解析 個人見解
阿新 • • 發佈:2018-12-31
<pre> * +------+ prev +-----+ +-----+ * head | | <---- | | <---- | | tail * +------+ +-----+ +-----+ * </pre>
import sun.misc.Unsafe;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractOwnableSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
private static final long serialVersionUID = 7373984972572414691L;
/**
* Creates a new {@code AbstractQueuedSynchronizer} instance
* with initial synchronization state of zero.
*/
//構造器
protected AbstractQueuedSynchronizer() {
}
//Node節點
static final class Node {
/**
* Marker to indicate a node is waiting in shared mode
*/
//共享鎖 newNode()相當於新建一個node節點
static final Node SHARED = new Node();
/**
* Marker to indicate a node is waiting in exclusive mode
*/
//獨佔鎖標識 null
static final Node EXCLUSIVE = null;
/**
* waitStatus value to indicate thread has cancelled
*/
//執行緒waitStatus標識 1 代表任務已結束
static final int CANCELLED = 1;
/**
* waitStatus value to indicate successor's thread needs unparking
*/
//waitStatus等待被喚醒
static final int SIGNAL = -1;
/**
* waitStatus value to indicate thread is waiting on condition
*/
//waitStatus在conditon單向連結串列的標識
static final int CONDITION = -2;
/**
* waitStatus value to indicate the next acquireShared should
* unconditionally propagate
*/
//waitStatus 嘗試獲取共享鎖傳播標識
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
* <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).
*/
//執行緒等待狀態標識 1,-1,-2,-3
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.
*/
//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.
*/
//指向node節點的下一個節點
volatile Node next;
/**
* The thread that enqueued this node. Initialized on
* construction and nulled out after use.
*/
//用於儲存node節點中的執行緒
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.
*/
//下一個等待者 用於condition單向連結串列佇列
Node nextWaiter;
/**
* Returns true if node is waiting in shared mode.
*/
//判斷是否為共享鎖
final boolean isShared() {
return nextWaiter == SHARED;
}
/**
* Returns previous node, or throws NullPointerException if null.
* Use when predecessor cannot be null. The null check could
* be elided, but is present to help the VM.
*
* @return the predecessor of this node
*/
//獲取當前節點的前驅節點,Node prev如果為null,throw 空指標異常
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
}
//構造器,用於codition中 addWaiter()佇列
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
//用於condition
Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread;
}
}
/**
* Head of the wait queue, lazily initialized. Except for
* initialization, it is modified only via method setHead. Note:
* If head exists, its waitStatus is guaranteed not to be
* CANCELLED.
*/
//頭節點
private transient volatile Node head;
/**
* Tail of the wait queue, lazily initialized. Modified only via
* method enq to add new wait node.、
* 等待佇列的尾部,延遲初始化。修改只能通過
* 方法enq新增新的等待節點。
*/
//尾節點
private transient volatile Node tail;
/**
* The synchronization state.
*/
//佇列中的state值 0,1,2,3,........ 0 初始化 1獨佔鎖 2可重入鎖 .....
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
*/
//當acciqure(int args) or release(int args) 等 需要設定狀態值
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.
*/
//CAS操作 設定state 狀態 expect 記憶體中的值 update 要更新的值
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
// Queuing utilities
/**
* The number of nanoseconds for which it is faster to spin
* rather than to use timed park. A rough estimate suffices
* to improve responsiveness with very short timeouts.
*/
static final long spinForTimeoutThreshold = 1000L;
/**
* Inserts node into queue, initializing if necessary. See picture above.
*
* @param node the node to insert
* @return node's predecessor
*/
//初始化node節點 將當前node節點插入SyncQueue同步佇列至尾節點
private Node enq(final Node node) {
//自旋
for (; ; ) {
//尾節點
Node t = tail;
//尾節點為Null,必須初始化同步SyncQueue佇列
if (t == null) { // Must initialize
//初始化頭節點
if (compareAndSetHead(new Node()))
//頭尾節點相連
tail = head;
} else {
//指向node節點的前驅節點
node.prev = t;
//t為尾節點時,CAS設定node節點為尾節點
if (compareAndSetTail(t, node)) {
//t ---> node 相當於調換位置,尾節點t變成了node的前節點 node變為尾節點
t.next = node;
//返回node尾節點的前一個節點
return t;
}
}
}
}
/**
* Creates and enqueues node for current thread and given mode.
* 為當前執行緒和給定模式建立和排隊節點。
*
* @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
* @return the new node
*/
private Node addWaiter(Node mode) {
//建立指向當前執行緒的node節點
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
//尾節點賦值pred
Node pred = tail;
if (pred != null) {
//尾節點指向node節點, 變換位置,node節點為尾節點,pred為node節點的前節點
//相當於雙向連結串列指標
node.prev = pred;
//node節點設定為佇列的尾節點
if (compareAndSetTail(pred, node)) {
pred.next = node;
//返回node節點
return node;
}
}
//如果尾節點為空,初始化 入列
enq(node);
//返回加入等待佇列的node節點
return node;
}
/**
* Sets head of queue to be node, thus dequeuing. Called only by
* acquire methods. Also nulls out unused fields for sake of GC
* and to suppress unnecessary signals and traversals.
*
* @param node the node
*/
//設定頭節點 等待被喚醒
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}
/**
* Wakes up node's successor, if one exists.
*
* @param node the node
*/
//喚醒節點的後續等待節點執行緒爭搶cpu資源
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.
*/
//獲取waitStatus 0,-1,-2,-3
int ws = node.waitStatus;
//ws<0代表該節點等待被喚醒
if (ws < 0)
//CAS設定waitStatus 為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.next node指向下一個節點
Node s = node.next;
//是否為null,或者狀態waitStatus>0 清除下一個節點
if (s == null || s.waitStatus > 0) {
s = null;
//從隊尾部向頭部依次遍歷,尋找waitStatus狀態為等待被喚醒的節點
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
//等待被喚醒的節點賦值給s
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.)
* <p>
* *共享模式釋放動作——訊號的後繼和保證
* *傳播。(注意:對於排他模式,釋放的數量是有限的
* *在需要訊號時,致電unpark繼承處的head。
* <p>
* 釋放共享模式的鎖
*/
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.
*
* 確保釋出能夠傳播,即使存在其他版本
*正在進行的獲得/版本。這一切照常進行
*如有需要,可嘗試將頭部後繼器取出
*訊號。但如果沒有,則將狀態設定為傳播到
*確保釋出後,傳播仍在繼續。
*此外,我們必須迴圈,以防新增新節點
當我們在做這件事的時候。而且,不像其他用法
* unpark繼承者,我們需要知道CAS是否重置狀態
*失敗,如果是,請重新檢查。
*/
//自旋
for (; ; ) {
//頭節點
Node h = head;
//判斷SyncQueue同步佇列是否只有一個節點
if (h != null && h != tail) {
//獲取頭節點狀態
int ws = h.waitStatus;
//狀態為-1 等待被喚醒
if (ws == Node.SIGNAL) {
//設定waitStatus狀態失敗 跳過
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue; // loop to recheck cases
//喚醒後續節點執行緒爭搶資源
unparkSuccessor(h);
//節點狀態為0 CAS waitStatus不能傳播 跳過
} else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
//從尾部向前直至到頭部 break
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.
* <p>
* 設定佇列頭,並檢查是否有後續佇列在等待
* *在共享模式下,如果是傳播,則傳播> 0或
* *設定傳播狀態
*
* @param node the node
* @param propagate the return value from a tryAcquireShared tryAcquireShared返回的值
*/
private void setHeadAndPropagate(Node node, int propagate) {
//記錄頭節點便於核對
Node h = head; // Record old head for check below
//當前節點設定為頭節點
setHead(node);
/*
* Try to signal next queued node if:
* Propagation was indicated by caller,
* or was recorded (as h.waitStatus either before
* or after setHead) by a previous operation
* (note: this uses sign-check of waitStatus because
* PROPAGATE status may transition to SIGNAL.)
* and
* The next node is waiting in shared mode,
* or we don't know, because it appears null
*
* The conservatism in both of these checks may cause
* unnecessary wake-ups, but only when there are multiple
* racing acquires/releases, so most need signals now or soon
* anyway.
*
*
如果:
*傳播由主叫人指示,
*或記錄(記為h。waitStatus要麼之前
*或在setHead之後)通過以前的操作
*(注意:這使用了sign-check of waitStatus,因為
*傳播狀態可能轉換為訊號。)
*和
*下一個節點在共享模式下等待,
或者我們不知道,因為它看起來是空的
*
*這兩種檢查中的穩健性都可能導致
*不必要的起床,但只有當有多的時候
*
*
*/
//tryAcquireShared嘗試獲取共享鎖的return value >表明獲取共享鎖成功
//等待狀態waitStatus<0等待被喚醒 or 頭節點為null
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
//指向node節點的下一個節點 s
Node s = node.next;
//s為null || 共享鎖
if (s == null || s.isShared())
//共享模式釋放 and 持續傳播
doReleaseShared();
}
}
// Utilities for various versions of acquire
/**
* Cancels an ongoing attempt to acquire.
* 取消正在嘗試獲取資源的節點
*
* @param node the node
*/
private void cancelAcquire(Node node) {
// Ignore if node doesn't exist
//節點是否存在
if (node == null)
return;
//設定thread 為null
node.thread = null;
// Skip cancelled predecessors
//跳過取消的前節點
Node pred = node.prev;
//waitStatus>0說明該節點被取消或已完成狀態
while (pred.waitStatus > 0)
//依次從尾向前尋找
node.prev = pred = pred.prev;
// predNext is the apparent node to unsplice. CASes below will
// fail if not, in which case, we lost race vs another cancel
// or signal, so no further action is necessary.
//下一個節點
Node predNext = pred.next;
// Can use unconditional write instead of CAS here.
// After this atomic step, other Nodes can skip past us.
// Before, we are free of interference from other threads.
//完成任務標識 waitStatus=1
node.waitStatus = Node.CANCELLED;
// If we are the tail, remove ourselves.
//如果node是尾節點,remove node節點
if (node == tail && compareAndSetTail(node, pred)) {
//CAS設定尾節點pred
compareAndSetNext(pred, predNext, null);
} else {
// If successor needs signal, try to set pred's next-link
// so it will get one. Otherwise wake it up to propagate.
int ws;
//如果後繼者需要訊號,試著設定pred的下一個連結
//所以它會得到一個signal。否則喚醒它傳播
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
//指向Node節點的next Node
Node next = node.next;
if (next != null && next.waitStatus <= 0)
//CAS設定pred的next節點為node,next next等待被喚醒
compareAndSetNext(pred, predNext, next);
} else {
//喚醒當前節點的後續節點
unparkSuccessor(node);
}
node.next = node; // help GC
}
}
/**
* Checks and updates status for a node that failed to acquire.
* Returns true if thread should block. This is the main signal
* control in all acquire loops. Requires that pred == node.prev.
* <p>
* 檢查和更新未能獲取的節點的狀態。
* 如果執行緒阻塞,返回true。這是主要訊號
* *控制所有的獲取迴圈。要求pred == node.prev。
*
* @param pred node's predecessor holding status
* @param node the node
* @return {@code true} if thread should block
*/
//檢查更新未能獲取資源的節點的狀態 執行緒阻塞則return true
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
//pred waitStatus
int ws = pred.waitStatus;
//-1 等待被喚醒
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
* 此節點已經設定了請求釋出的狀態
*發出訊號,以便安全停車。
*/
//可掛起阻塞狀態 park 重量級鎖
return true;
//等待狀態>0 跳過
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
do {
//從佇列尾部依次向頭節點尋找 waitStatus<=0的節點
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
//設定pred的下個節點為node節點
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.
*
* waitStatus必須為0或PROPAGATE。表明我們
需要訊號,但不要停車。來電者需要
* 停車前請務必確認無法獲取。
*/
//設定狀態為signal 等待被喚醒
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
/**
* Convenience method to interrupt current thread.
*/
//當前執行緒自我中斷
static void selfInterrupt() {
Thread.currentThread().interrupt();
}
/**
* Convenience method to park and then check if interrupted
*
* @return {@code true} if interrupted
*/
//當前執行緒掛起並check是否中斷過
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
/*
* Various flavors of acquire, varying in exclusive/shared and
* control modes. Each is mostly the same, but annoyingly
* different. Only a little bit of factoring is possible due to
* interactions of exception mechanics (including ensuring that we
* cancel if tryAcquire throws exception) and other control, at
* least not without hurting performance too much.
*/
/**
* Acquires in exclusive uninterruptible mode for thread already in
* queue. Used by condition wait methods as well as acquire.
* <p>
* 為已經在的執行緒獲取獨佔的不可中斷模式
* *佇列。用於條件等待方法和獲取方法。
*
* @param node the node
* @param arg the acquire argument
* @return {@code true} if interrupted while waiting
*/
//使執行緒在等待佇列中獲取資源,一直獲取到資源後才返回。
// 如果在整個等待過程中被中斷過,則返回true,否則返回false。
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
//中斷標識
boolean interrupted = false;
//自旋
for (; ; ) {
//獲取node前驅節點
final Node p = node.predecessor();
//頭節點 and node獲取鎖成功
if (p == head && tryAcquire(arg)) {
//設定node節點為頭節點
setHead(node);
//p.next=null
p.next = null; // help GC
failed = false;
//不可中斷
return interrupted;
}
//檢查更新未能獲取資源的節點的狀態 park node 掛起node節點
if (shouldParkAfterFailedAcquire(p, node) &&
//執行緒掛起 檢查是否被中斷
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
//失敗清除
if (failed)
//清除node節點
cancelAcquire(node);
}
}
/**
* Acquires in exclusive interruptible mode.
* 獲取獨佔鎖/排它鎖的中斷模式
*
* @param arg the acquire argument
*/
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
//Thread.currentThread獨佔鎖node
final Node node = addWaiter(Node.EXCLUSIVE);
//失敗標識
boolean failed = true;
try {
//自旋
for (; ; ) {
//前驅節點
final Node p = node.predecessor();
//前驅節點為head頭節點,並且當前節點能獲取到資源
if (p == head && tryAcquire(arg)) {
//設定當前節點為頭節點
setHead(node);
p.next = null; // help GC
failed = false;
return;
}
//是否可中斷 interrupt and 掛起 park
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
//clean up node 清除當前節點
cancelAcquire(node);
}
}
/**
* Acquires in exclusive timed mode.
* <p>
* 在一定時間內獲取獨佔鎖
*
* @param arg the acquire argument
* @param nanosTimeout max wait time
* @return {@code true} if acquired
*/
private boolean doAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
//時間<=0 false
if (nanosTimeout <= 0L)
return false;
//系統計數當前時間+獲取時間 用於後面判斷是否超時
final long deadline = System.nanoTime() + nanosTimeout;
//獨佔鎖入列
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
//自旋
for (; ; ) {
//前驅節點
final Node p = node.predecessor();
//前節點為頭節點 and 當前執行緒的節點可獲取鎖成功
if (p == head && tryAcquire(arg)) {
//設定當前節點為頭節點等待被喚醒
setHead(node);
p.next = null; // help GC
failed = false;
return true;
}
//用於判斷是否超時
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L)
return false;
//是否可以中斷 and park掛起
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
//中斷拋異常標識處理
throw new InterruptedException();
}
} finally {
//失敗
if (failed)
//獲取失敗,清除當前節點
cancelAcquire(node);
}
}
/**
* Acquires in shared uninterruptible mode.
* 獲得共享鎖不可中斷模式
*
* @param arg the acquire argument
*/
private void doAcquireShared(int arg) {
//共享addWaiter入列排隊
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;
}
}
//是否可以中斷 and park 阻塞
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
//清除當前節點
cancelAcquire(node);
}
}
/**
* Acquires in shared interruptible mode.
* 獲取共享鎖的可中斷模式
*
* @param arg the acquire argument
*/
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
//當前節點共享模式入列
final Node node = addWaiter(Node.SHARED);
//清除節點標識
boolean failed = true;
try {
//自旋
for (; ; ) {
//獲取前驅節點
final Node p = node.predecessor();
//前驅節點==head頭節點
if (p == head) {
//當前節點嘗試獲取共享鎖
int r = tryAcquireShared(arg);
//獲取重入次數
if (r >= 0) {
//設定當前節點為頭節點,並傳播
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
//當前執行緒是否阻塞 and中斷
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
//清除當前節點
cancelAcquire(node);
}
}
/**
* Acquires in shared timed mode.
* 一定時間內嘗試獲取共享鎖
*
* @param arg the acquire argument
* @param nanosTimeout max wait time
* @return {@code true} if acquired
*/
private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
//獲取時間<=0 不能獲取
if (nanosTimeout <= 0L)
return false;
//用於計算超時
final long deadline = System.nanoTime() + nanosTimeout;
//當前執行緒的節點入列
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
//自旋
for (; ; ) {
//前驅節點
final Node p = node.predecessor();
//判斷是否為頭節點
if (p == head) {
//共享鎖的可重入次數
int r = tryAcquireShared(arg);
if (r >= 0) {
//設定頭節點並傳播
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return true;
}
}
//計算是否超時
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L)
return false;
//是否阻塞 park and interrupt中斷
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
if (failed)
//清除node節點
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()}.
*
* <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) {
/*
int c= getState();
if (Thread.currentThread()==getExclusiveOwnerThread()){
int i = c + arg;
if (i<0){
throw new UnsupportedOperationException("");
}
setState(i);
}else{
acquire(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.
* @throws IllegalMonitorStateException if releasing would place this
* synchronizer in an illegal state. This exception must be
* thrown in a consistent fashion for synchronization to work
* correctly.
* @throws UnsupportedOperationException if exclusive mode is not supported
*/
//嘗試釋放鎖資源
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
/**
* Attempts to acquire in shared mode. This method should query if
* the state of the object permits it to be acquired in the shared
* mode, and if so to acquire it.
*
* <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();
}
/**
* 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();
}
/**
* 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
*/
//是否為獨佔鎖/排它鎖
protected boolean isHeldExclusively() {
throw new UnsupportedOperationException();
}
/**
* Acquires in exclusive mode, ignoring interrupts. Implemented
* by invoking at least once {@link #tryAcquire},
* returning on success. Otherwise the thread is queued, possibly
* repeatedly blocking and unblocking, invoking {@link
* #tryAcquire} until success. This method can be used
* to implement method {@link Lock#lock}.
*
* @param arg the acquire argument. This value is conveyed to
* {@link #tryAcquire} but is otherwise uninterpreted and
* can represent anything you like.
*/
//獲取獨佔鎖的入口
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
//使執行緒在等待佇列中獲取資源,一直獲取到資源後才返回。
// 如果在整個等待過程中被中斷過,則返回true,否則返回false。
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
/**
* Acquires in exclusive mode, aborting if interrupted.
* Implemented by first checking interrupt status, then invoking
* at least once {@link #tryAcquire}, returning on
* success. Otherwise the thread is queued, possibly repeatedly
* blocking and unblocking, invoking {@link #tryAcquire}
* until success or the thread is interrupted. This method can be
* used to implement method {@link Lock#lockInterruptibly}.
*
* @param arg the acquire argument. This value is conveyed to
* {@link #tryAcquire} but is otherwise uninterpreted and
* can represent anything you like.
* @throws InterruptedException if the current thread is interrupted
*/
//獲取可中斷的獨佔鎖入口
public final void acquireInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
}
/**
* Attempts to acquire in exclusive mode, aborting if interrupted,
* and failing if the given timeout elapses. Implemented by first
* checking interrupt status, then invoking at least once {@link
* #tryAcquire}, returning on success. Otherwise, the thread is
* queued, possibly repeatedly blocking and unblocking, invoking
* {@link #tryAcquire} until success or the thread is interrupted
* or the timeout elapses. This method can be used to implement
* method {@link Lock#tryLock(long, TimeUnit)}.
*
* @param arg the acquire argument. This value is conveyed to
* {@link #tryAcquire} but is otherwise uninterpreted and
* can represent anything you like.
* @param nanosTimeout the maximum number of nanoseconds to wait
* @return {@code true} if acquired; {@code false} if timed out
* @throws InterruptedException if the current thread is interrupted
*/
//一定時間內嘗試獲取鎖資源
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquire(arg) ||
doAcquireNanos(arg, nanosTimeout);
}
/**
* Releases in exclusive mode. Implemented by unblocking one or
* more threads if {@link #tryRelease} returns true.
* This method can be used to implement method {@link Lock#unlock}.
*
* @param arg the release argument. This value is conveyed to
* {@link #tryRelease} but is otherwise uninterpreted and
* can represent anything you like.
* @return the value returned from {@link #tryRelease}
*/
//釋放鎖資源
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
//釋放鎖資源
unparkSuccessor(h);
return true;
}
return false;
}
/**
* Acquires in shared mode, ignoring interrupts. Implemented by
* first invoking at least once {@link #tryAcquireShared},
* returning on success. Otherwise the thread is queued, possibly
* repeatedly blocking and unblocking, invoking {@link
* #tryAcquireShared} until success.
*
* @param arg the acquire argument. This value is conveyed to
* {@link #tryAcquireShared} but is otherwise uninterpreted
* and can represent anything you like.
*/
//嘗試獲取共享鎖
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
/**
* Acquires in shared mode, aborting if interrupted. Implemented
* by first checking interrupt status, then invoking at least once
* {@link #tryAcquireShared}, returning on success. Otherwise the
* thread is queued, possibly repeatedly blocking and unblocking,
* invoking {@link #tryAcquireShared} until success or the thread
* is interrupted.
*
* @param arg the acquire argument.
* This value is conveyed to {@link #tryAcquireShared} but is
* otherwise uninterpreted and can represent anything
* you like.
* @throws InterruptedException if the current thread is interrupted
*/
//嘗試獲取可中斷的共享鎖
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
/**
* Attempts to acquire in shared mode, aborting if interrupted, and
* failing if the given timeout elapses. Implemented by first
* checking interrupt status, then invoking at least once {@link
* #tryAcquireShared}, returning on success. Otherwise, the
* thread is queued, possibly repeatedly blocking and unblocking,
* invoking {@link #tryAcquireShared} until success or the thread
* is interrupted or the timeout elapses.
*
* @param arg the acquire argument. This value is conveyed to
* {@link #tryAcquireShared} but is otherwise uninterpreted
* and can represent anything you like.
* @param nanosTimeout the maximum number of nanoseconds to wait
* @return {@code true} if acquired; {@code false} if timed out
* @throws InterruptedException if the current thread is interrupted
*/
//一定時間內嘗試獲取共享鎖資源
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquireShared(arg) >= 0 ||
doAcquireSharedNanos(arg, nanosTimeout);
}
/**
* Releases in shared mode. Implemented by unblocking one or more
* threads if {@link #tryReleaseShared} returns true.
*
* @param arg the release argument. This value is conveyed to
* {@link #tryReleaseShared} but is otherwise uninterpreted
* and can represent anything you like.
* @return the value returned from {@link #tryReleaseShared}
*/
//釋放共享鎖 可重寫 tryReleaseShared()
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
// Queue inspection methods
/**
* Queries whether any threads are waiting to acquire. Note that
* because cancellations due to interrupts and timeouts may occur
* at any time, a {@code true} return does not guarantee that any
* other thread will ever acquire.
*
* <p>In this implementation, this operation returns in
* constant time.
*
* @return {@code true} if there may be other threads waiting to acquire
*/
//佇列中是否有執行緒
public final boolean hasQueuedThreads() {
return head != tail;
}
/**
* Queries whether any threads have ever contended to acquire this
* synchronizer; that is if an acquire method has ever blocked.
*
* <p>In this implementation, this operation returns in
* constant time.
*
* @return {@code true} if there has ever been contention
*/
public final boolean hasContended() {
return head != null;
}
/**
* Returns the first (longest-waiting) thread in the queue, or
* {@code null} if no threads are currently queued.
*
* <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
*/
//獲取佇列中等待的第一個執行緒
public final Thread getFirstQueuedThread() {
// handle only fast path, else relay
return (head == tail) ? null : fullGetFirstQueuedThread();
}
/**
* Version of getFirstQueuedThread called when fastpath fails
*/
private Thread fullGetFirstQueuedThread() {
/*
* The first node is normally head.next. Try to get its
* thread field, ensuring consistent reads: If thread
* field is nulled out or s.prev is no longer head, then
* some other thread(s) concurrently performed setHead in
* between some of our reads. We try this twice before
* resorting to traversal.
*/
Node h, s;
Thread st;
//獲取佇列中的執行緒
if (((h = head) != null && (s = h.next) != null &&
s.prev == head && (st = s.thread) != null) ||
((h = head) != null && (s = h.next) != null &&
s.prev == head && (st = s.thread) != null))
return st;
/*
* Head's next field might not have been set yet, or may have
* been unset after setHead. So we must check to see if tail
* is actually first node. If not, we continue on, safely
* traversing from tail back to head to find first,
* guaranteeing termination.
*/
//尾節點
Node t = tail;
Thread firstThread = null;
//從尾部依次向頭部迴圈,直至找到firstThread
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.
*
* <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
* @throws NullPointerException if the thread is null
*/
//當前執行緒是否在佇列中
public final boolean isQueued(Thread thread) {
if (thread == null)
throw new NullPointerException();
//從尾部向頭部依次遍歷尋找當前執行緒是否在佇列中
for (Node p = tail; p != null; p = p.prev)
if (p.thread == thread)
return true;
return false;
}
/**
* Returns {@code true} if the apparent first queued thread, if one
* exists, is waiting in exclusive mode. If this method returns
* {@code true}, and the current thread is attempting to acquire in
* shared mode (that is, this method is invoked from {@link
* #tryAcquireShared}) then it is guaranteed that the current thread
* is not the first queued thread. Used only as a heuristic in
* ReentrantReadWriteLock.
*/
//頭節點是否為獨佔鎖/排他鎖
final boolean apparentlyFirstQueuedIsExclusive() {
Node h, s;
return (h = head) != null &&
(s = h.next) != null &&
!s.isShared() &&
s.thread != null;
}
/**
* Queries whether any threads have been waiting to acquire longer
* than the current thread.
*
* <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.
*
* <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:
*
* <pre> {@code
* protected boolean tryAcquire(int arg) {
* if (isHeldExclusively()) {
* // A reentrant acquire; increment hold count
* return true;
* } else if (hasQueuedPredecessors()) {
* return false;
* } else {
* // try to acquire normally
* }
* }}</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
* @since 1.7
*/
//在佇列中是否有前驅節點
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
// Instrumentation and monitoring methods
/**
* Returns an estimate of the number of threads waiting to
* acquire. The value is only an estimate because the number of
* threads may change dynamically while this method traverses
* internal data structures. This method is designed for use in
* monitoring system state, not for synchronization
* control.
*
* @return the estimated number of threads waiting to acquire
*/
//獲取佇列中的長度
public final int getQueueLength() {
int n = 0;
for (Node p = tail; p != null; p = p.prev) {
if (p.thread != null)
++n;
}
return n;
}
/**
* Returns a collection containing threads that may be waiting to
* acquire. Because the actual set of threads may change
* dynamically while constructing this result, the returned
* collection is only a best-effort estimate. The elements of the
* returned collection are in no particular order. This method is
* designed to facilitate construction of subclasses that provide
* more extensive monitoring facilities.
*
* @return the collection of threads
*/
//獲取佇列中所有執行緒的集合
public final Collection<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.
*
* @return the collection of threads
*/
//獲取佇列中獨佔鎖/排他鎖 模式下執行緒的集合
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.
*
* @return the collection of threads
*/
//獲取共享鎖的執行緒集合
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.
*
* @param node the node
* @return true if is reacquiring
*/
//是否在syncQueue佇列中
final boolean isOnSyncQueue(Node node) {
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
if (node.next != null) // If has successor, it must be on queue
return true;
/*
* node.prev can be non-null, but not yet on queue because
* the CAS to place it on queue can fail. So we have to
* traverse from tail to make sure it actually made it. It
* will always be near the tail in calls to this method, and
* unless the CAS failed (which is unlikely), it will be
* there, so we hardly ever traverse much.
*/
//從尾部至頭部依次查詢
return findNodeFromTail(node);
}
/**
* Returns true if node is on sync queue by searching backwards from tail.
* Called only when needed by isOnSyncQueue.
*
* @return true if present
*/
//從尾部至頭部依次查詢
private boolean findNodeFromTail(Node node) {
Node t = tail;
for (; ; ) {
if (t == node)
return true;
if (t == null)
return false;
t = t.prev;
}
}
/**
* Transfers a node from a condition queue onto sync queue.
* Returns true if successful.
*
* @param node the node
* @return true if successfully transferred (else the node was
* cancelled before signal)
*/
//轉換當前節點狀態為signal
final boolean transferForSignal(Node node) {
/*
* If cannot change waitStatus, the node has been cancelled.
*/
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
/*
* Splice onto queue and try to set waitStatus of predecessor to
* indicate that thread is (probably) waiting. If cancelled or
* attempt to set waitStatus fails, wake up to resync (in which
* case the waitStatus can be transiently and harmlessly wrong).
*/
//增加Node節點為尾節點
Node p = enq(node);
//p node的前驅節點
int ws = p.waitStatus;
//不能轉換,喚醒當前執行緒
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
/**
* Transfers node, if necessary, to sync queue after a cancelled wait.
* Returns true if thread was cancelled before being signalled.
*
* @param node the node
* @return true if cancelled before the node was signalled
*/
//轉換當前節點為condition狀態 標識 可入列condition單向連結串列佇列
final boolean transferAfterCancelledWait(Node node) {
if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
enq(node);
return true;
}
/*
* If we lost out to a signal(), then we can't proceed
* until it finishes its enq(). Cancelling during an
* incomplete transfer is both rare and transient, so just
* spin.
*/
//不在SyncQueue中的node節點
while (!isOnSyncQueue(node))
//當前執行緒放棄資源,重新爭搶資源
Thread.yield();
return false;
}
/**
* Invokes release with current state value; returns saved state.
* Cancels node and throws exception on failure.
*
* @param node the condition node for this wait
* @return previous sync state
*/
//釋放
final int fullyRelease(Node node) {
boolean failed = true;
try {
//獲取狀態 0,1,2,...
int savedState = getState();
if (release(savedState)) {
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateExc