/**
* 加鎖
*/
public final void acquire(int arg) {
// 首先嚐試獲取,如果獲取成功直接退出;如果獲取失敗,即競爭鎖失敗,則創建Node,並添加到同步隊列尾部。
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
private Node addWaiter(Node mode) {
// 創建節點,mode此時爲null,表示下一個等待節點爲空
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;
}
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;
}
}
}
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
/* 前驅爲頭結點且嘗試獲取同步狀態成功,則將當前節點設置爲頭節點,原頭結點解勾;
並返回false,用於finally決定是否取消獲取同步狀態;
*/
if (p == head && tryAcquire(arg)) {
// 如果當前結點獲取同步狀態成功了,那麼將當前節點設置爲頭結點。
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// 如果獲取同步狀態失敗,檢查是否需要阻塞線程
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
/*
0:初始化
CANCELLED = 1 :線程等待超時或者被中斷了,需要從同步隊列中移走
SIGNAL = -1 :後續的節點等待狀態,當前節點,通知後面的節點去運行
CONDITION = -2 :當前節點處於等待隊列
PROPAGATE = -3 :共享,表示狀態要往後面的節點傳播
*/
// 獲取前驅的狀態碼
int ws = pred.waitStatus;
// 如果前驅狀態碼爲 SIGNAL,則返回true,表示當前線程需要阻塞
if (ws == Node.SIGNAL)
return true;
// 如果前驅狀態碼>0,即前驅已經取消,則將同步隊列中從該節點起,所有狀態爲取消的前驅一律解勾
if (ws > 0) {
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
// 代碼運行到這裏,狀態一般只可能爲0、-2或者-3,此時將前驅狀態設置爲 SIGNAL
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
private final boolean parkAndCheckInterrupt() {
// 阻塞當前線程,並返回是否被中斷的狀態,底層使用UNSAFE.park(false, 0L);public native void park(boolean var1, long var2);
LockSupport.park(this);
return Thread.interrupted();
}
/**
* 釋放鎖
*/
public final boolean release(int arg) {
// 這裏是模板方法,由子類實現;如果狀態修改成功,則後續邏輯將釋放鎖
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
// s.waitStatus > 0,表明該結點已被取消
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)
// 喚醒線程,底層由UNSAFE.unpark(thread)實現。public native void unpark(Object var1);
LockSupport.unpark(s.thread);
}