AQS——AbstractQueuedSynchronizer 同步框架(基于JDK14)
1、結(jié)構(gòu)說明
AbstractQueuedSynchronizer 繼承 AbstractOwnableSynchronizer,含有五個(gè)內(nèi)部類,其中比較重要的是Node,ConditionNode及ConditionObject。下面是具體類圖(由于AbstractQueuedSynchronizer 方法太多,此處已屏蔽大多數(shù)方法):
AbstractOwnableSynchronizer:
AbstractQueuedSynchronizer 的父類,主要是設(shè)置當(dāng)前獨(dú)占鎖的線程:
public abstract class AbstractOwnableSynchronizer
implements java.io.Serializable {
/** Use serial ID even though all fields transient. */
private static final long serialVersionUID = 3737899427754241961L;
/**
* Empty constructor for use by subclasses.
*/
protected AbstractOwnableSynchronizer() { }
/**
* The current owner of exclusive mode synchronization.
*/
private transient Thread exclusiveOwnerThread;
/**
* Sets the thread that currently owns exclusive access.
* A {@code null} argument indicates that no thread owns access.
* This method does not otherwise impose any synchronization or
* {@code volatile} field accesses.
* @param thread the owner thread
* 設(shè)置獨(dú)占鎖
*/
protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
/**
* Returns the thread last set by {@code setExclusiveOwnerThread},
* or {@code null} if never set. This method does not otherwise
* impose any synchronization or {@code volatile} field accesses.
* @return the owner thread
* 獲取獨(dú)占鎖
*/
protected final Thread getExclusiveOwnerThread() {
return exclusiveOwnerThread;
}
}
Node:節(jié)點(diǎn)類,AQS隊(duì)列的節(jié)點(diǎn),包含prev,next,由此可以看出,AQS隊(duì)列是個(gè)基于鏈表實(shí)現(xiàn)的雙向隊(duì)列。waiter為在該節(jié)點(diǎn)的線程,既等待獲取鎖的線程。status用來標(biāo)識(shí)當(dāng)前節(jié)點(diǎn)線程的狀態(tài),有以下值:
表示節(jié)點(diǎn)的狀態(tài)。其中包含的狀態(tài)有(此處有待):
- CANCELLED,值小于0,表示當(dāng)前的線程被取消;
- COND,值為 2,表示當(dāng)前節(jié)點(diǎn)在等待condition,也就是在condition隊(duì)列中(此時(shí)Node的實(shí)際值是3);
- WAITING,值為1,表示當(dāng)前節(jié)點(diǎn)在sync隊(duì)列中,等待著獲取鎖;
ExclusiveNode:獨(dú)占鎖節(jié)點(diǎn),繼承Node,無擴(kuò)展;
SharedNode:共享鎖節(jié)點(diǎn),繼承Node,無擴(kuò)展;
ConditionNode:繼承Node,與Node相比,多了nextWaiter屬性(),為Condition隊(duì)列的節(jié)點(diǎn);
// Node status bits, also used as argument and return values
static final int WAITING = 1; // must be 1
static final int CANCELLED = 0x80000000; // must be negative
static final int COND = 2; // in a condition wait
static final class ConditionNode extends Node
implements ForkJoinPool.ManagedBlocker {
ConditionNode nextWaiter; // link to next waiting node
/**
* Allows Conditions to be used in ForkJoinPools without
* risking fixed pool exhaustion. This is usable only for
* untimed Condition waits, not timed versions.
*/
public final boolean isReleasable() {
return status <= 1 || Thread.currentThread().isInterrupted();
}
public final boolean block() {
while (!isReleasable()) LockSupport.park();
return true;
}
}
ConditionObject:實(shí)現(xiàn)了Condition的接口,提供操作Condition隊(duì)列方法,主要包含Condition類型的firstWaiter及l(fā)astWaiter屬性(隊(duì)列頭及隊(duì)列尾);這個(gè)類是為了讓子類支持獨(dú)占模式的。await()、sign()
方法就是讓線程阻塞、加入隊(duì)列、喚醒線程。AQS框架下基本各種獨(dú)占的加鎖,解鎖等操作到最后都是基于這個(gè)類實(shí)現(xiàn)的。
該類是提供給子類去使用的,在Reentrantlock有相關(guān)的使用。有人可能覺得為什么實(shí)現(xiàn)這個(gè)內(nèi)部類,又不用,而是給子類去用,那為什么不放到子類去呢?其實(shí)答案,很簡(jiǎn)單,抽象加模板模式。
public class ConditionObject implements Condition, java.io.Serializable {
private static final long serialVersionUID = 1173984872572414699L;
/** First node of condition queue. */
private transient ConditionNode firstWaiter;
/** Last node of condition queue. */
private transient ConditionNode lastWaiter;
...
}
從以上的結(jié)構(gòu)可以看出,AQS中包含兩個(gè)隊(duì)列,一個(gè)是由Node組成的雙向隊(duì)列,也就是同步隊(duì)列,另一個(gè)則是由ConditionNode組成的單向隊(duì)列,即Condition隊(duì)列。Condition隊(duì)列由ConditionObject操作,ConditionObject實(shí)現(xiàn)Condition接口。
兩個(gè)隊(duì)列的關(guān)系如下圖所示(此圖來自網(wǎng)絡(luò)):
2、同步隊(duì)列
AQS是一個(gè)基礎(chǔ)的同步框架,只是定義了部分基礎(chǔ)的方法,具體實(shí)現(xiàn)部分交由子類去實(shí)現(xiàn),以便擴(kuò)展不同的功能。
獲取鎖的流程如下:
可以看出來,在線程未暫停之前,每進(jìn)行一次循環(huán),都會(huì)調(diào)用tryAcquire/tryAcquireShared方法。
加入同步隊(duì)列(同時(shí),離隊(duì)也在該方法中實(shí)現(xiàn)):
//子類進(jìn)入同步隊(duì)列時(shí),調(diào)用此方法
public final void acquire(int arg) {
//tryAcquire方法交由子類去實(shí)現(xiàn)
if (!tryAcquire(arg))
acquire(null, arg, false, false, false, 0L);
}
final int acquire(Node node, int arg, boolean shared,
boolean interruptible, boolean timed, long time) {
Thread current = Thread.currentThread();
byte spins = 0, postSpins = 0; // retries upon unpark of first thread
//first表示當(dāng)前node是否是head的下一個(gè)節(jié)點(diǎn),在出隊(duì)時(shí)需要
boolean interrupted = false, first = false;
Node pred = null; // predecessor of node when enqueued
/*
* Repeatedly:
* Check if node now first
* if so, ensure head stable, else ensure valid predecessor
* if node is first or not yet enqueued, try acquiring
* else if node not yet created, create it
* else if not yet enqueued, try once to enqueue
* else if woken from park, retry (up to postSpins times)
* else if WAITING status not set, set and retry
* else park and clear WAITING status, and check cancellation
*/
//第一次調(diào)用時(shí),此時(shí)的node必定為null(conditionNode獲取鎖時(shí),此時(shí)node不為null)
//當(dāng)初始化node之后,node的prev、next等都是null
for (;;) {
//first == false 且 node不為null,node的前置節(jié)點(diǎn)不為null,node的前置節(jié)點(diǎn)不是head節(jié)點(diǎn)
if (!first && (pred = (node == null) ? null : node.prev) != null &&
!(first = (head == pred))) {
//node 的status < 0
if (pred.status < 0) {
//清除已取消的節(jié)點(diǎn)
//這個(gè)方法暫時(shí)沒看懂
cleanQueue(); // predecessor cancelled
continue;
} else if (pred.prev == null) {
//進(jìn)入此步的情景:同步隊(duì)列只有一個(gè)節(jié)點(diǎn)(即head的prev才會(huì)等于null),但是if條件中
//限制了這種情景
//這步?jīng)]看懂
Thread.onSpinWait(); // ensure serialization
continue;
}
}
if (first || pred == null) {
boolean acquired;
try {
//此處,調(diào)用子類的 tryAcquire/tryAcquireShared 的實(shí)現(xiàn)。如果成功,則獲取鎖,不進(jìn)入同步隊(duì)列(cas修改status變量)
//相比JDK1.8,此處是一個(gè)小優(yōu)化,當(dāng)線程在進(jìn)入同步隊(duì)列期間,線程還沒暫停之前,在執(zhí)行方法進(jìn)入同步方法時(shí),不時(shí)直接去獲取鎖,
//在并發(fā)較低的場(chǎng)景下,省去了進(jìn)入隊(duì)列、暫停線程的操作;但是在并發(fā)較高的情況下,tryAcquire基本是失敗的,多了tryAcquire的消耗。
//線程被喚醒之后,也會(huì)通過此處獲取鎖,走出循環(huán)
//共享鎖
if (shared)
acquired = (tryAcquireShared(arg) >= 0);
else
//獨(dú)占鎖
acquired = tryAcquire(arg);
} catch (Throwable ex) {
cancelAcquire(node, interrupted, false);
throw ex;
}
//獲取鎖成功
if (acquired) {
if (first) {
//離隊(duì)
node.prev = null;
head = node;
pred.next = null;
node.waiter = null;
if (shared)
signalNextIfShared(node);
if (interrupted)
current.interrupt();
}
return 1;
}
}
//根據(jù)是否是獨(dú)占鎖,創(chuàng)建對(duì)應(yīng)的節(jié)點(diǎn)
if (node == null) { // allocate; retry before enqueue
if (shared)
node = new SharedNode();
else
node = new ExclusiveNode();
} else if (pred == null) { // try to enqueue
//初始化節(jié)點(diǎn)
node.waiter = current;
Node t = tail;
//尾節(jié)點(diǎn)
node.setPrevRelaxed(t); // avoid unnecessary fence
if (t == null)
//初始化頭尾節(jié)點(diǎn)(head == tail)
tryInitializeHead();
//cas修改尾節(jié)點(diǎn)和新節(jié)點(diǎn)(即移動(dòng)tail節(jié)點(diǎn)的位置)
//此處是節(jié)點(diǎn)入隊(duì)列的關(guān)鍵操作
else if (!casTail(t, node))
node.setPrevRelaxed(null); // back out
else
t.next = node;
} else if (first && spins != 0) {
//非公平鎖時(shí)會(huì)進(jìn)入該步驟
//即線程被喚醒,卻沒有獲取到鎖
--spins; // reduce unfairness on rewaits
//jdk9新方法,優(yōu)化自旋 改善自旋等待循環(huán)中的響應(yīng)時(shí)間
Thread.onSpinWait();
} else if (node.status == 0) {
//初始化status
node.status = WAITING; // enable signal and recheck
} else {
long nanos;
spins = postSpins = (byte)((postSpins << 1) | 1);
if (!timed)
//暫停線程
LockSupport.park(this);
else if ((nanos = time - System.nanoTime()) > 0L)
LockSupport.parkNanos(this, nanos);
else
break;
//被喚醒,此時(shí)清除狀態(tài)
node.clearStatus();
if ((interrupted |= Thread.interrupted()) && interruptible)
break;
}
}
return cancelAcquire(node, interrupted, interruptible);
}
喚醒線程,通知線程離隊(duì):
public final boolean release(int arg) {
//調(diào)用子類方法
if (tryRelease(arg)) {
//喚醒下一個(gè)節(jié)點(diǎn)
signalNext(head);
return true;
}
return false;
}
private static void signalNext(Node h) {
Node s;
if (h != null && (s = h.next) != null && s.status != 0) {
//設(shè)置等待狀態(tài)(此時(shí)該節(jié)點(diǎn)的線程將要被喚醒)
s.getAndUnsetStatus(WAITING);
//喚醒線程
LockSupport.unpark(s.waiter);
}
}
3、Condition隊(duì)列
Condition隊(duì)列是獨(dú)立與同步隊(duì)列的隊(duì)列,一個(gè)同步隊(duì)列可以對(duì)應(yīng)多個(gè)Condition隊(duì)列。
入隊(duì):
/**
* Implements interruptible condition wait.
* <ol>
* <li>If current thread is interrupted, throw InterruptedException.
* <li>Save lock state returned by {@link #getState}.
* <li>Invoke {@link #release} with saved state as argument,
* throwing IllegalMonitorStateException if it fails.
* <li>Block until signalled or interrupted.
* <li>Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
* <li>If interrupted while blocked in step 4, throw InterruptedException.
* </ol>
*/
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//構(gòu)造ConditionNode
ConditionNode node = new ConditionNode();
//填充conditionNode,并且condition隊(duì)列入隊(duì),同步隊(duì)列離隊(duì)
int savedState = enableWait(node);
//暫存線程 jdk14新方法
LockSupport.setCurrentBlocker(this); // for back-compatibility
boolean interrupted = false, cancelled = false;
//當(dāng)node不在condition隊(duì)列時(shí),當(dāng)線程被喚醒時(shí),node已不在condition隊(duì)列,而是在同步隊(duì)列
while (!canReacquire(node)) {
if (interrupted |= Thread.interrupted()) {
//如果線程被中斷并且當(dāng)前狀態(tài)值為3
//COND 按位非得 mask = -(COND+1),status = status & mask,
//mask == -3,以status的取值,只有當(dāng)status == 3時(shí),才退出
if (cancelled = (node.getAndUnsetStatus(COND) & COND) != 0)
break; // else interrupted after signal
} else if ((node.status & COND) != 0) {
try {
//掛起線程,調(diào)用 ConditionNode 的block方法
// 喚醒條件:
// status <= 1 || Thread.currentThread().isInterrupted()
ForkJoinPool.managedBlock(node);
} catch (InterruptedException ie) {
interrupted = true;
}
} else
Thread.onSpinWait(); // awoke while enqueuing
}
LockSupport.setCurrentBlocker(null);
node.clearStatus();
//重新競(jìng)爭(zhēng)鎖
acquire(node, savedState, false, false, false, 0L);
if (interrupted) {
if (cancelled) {
unlinkCancelledWaiters(node);
throw new InterruptedException();
}
Thread.currentThread().interrupt();
}
}
/**
* Adds node to condition list and releases lock.
*
* @param node the node
* @return savedState to reacquire after wait
*/
private int enableWait(ConditionNode node) {
//是否持有獨(dú)占鎖
if (isHeldExclusively()) {
//設(shè)置node的線程
node.waiter = Thread.currentThread();
//coonditionNode的status 為2|1 = 3
node.setStatusRelaxed(COND | WAITING);
ConditionNode last = lastWaiter;
//進(jìn)入condition隊(duì)列
if (last == null)
firstWaiter = node;
else
last.nextWaiter = node;
lastWaiter = node;
//獲取status
int savedState = getState();
//釋放鎖,注意,進(jìn)入condition隊(duì)列將釋放鎖,且離開同步隊(duì)列
if (release(savedState))
return savedState;
}
node.status = CANCELLED; // lock not held or inconsistent
throw new IllegalMonitorStateException();
}
出隊(duì):
/**
* Moves the longest-waiting thread, if one exists, from the
* wait queue for this condition to the wait queue for the
* owning lock.
*
* @throws IllegalMonitorStateException if {@link #isHeldExclusively}
* returns {@code false}
*/
public final void signal() {
ConditionNode first = firstWaiter;
//如果當(dāng)前線程沒有獨(dú)占鎖的話,拋異常
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
if (first != null)
//condition隊(duì)列還有節(jié)點(diǎn)
doSignal(first, false);
}
/**
* Removes and transfers one or all waiters to sync queue.
*/
private void doSignal(ConditionNode first, boolean all) {
while (first != null) {
ConditionNode next = first.nextWaiter;
if ((firstWaiter = next) == null)
lastWaiter = null;
//此處判斷status是否等于3,即是否處于等待中
if ((first.getAndUnsetStatus(COND) & COND) != 0) {
//重新進(jìn)入同步隊(duì)列隊(duì)尾
enqueue(first);
if (!all)
break;
}
first = next;
}
}
/**
* Enqueues the node unless null. (Currently used only for
* ConditionNodes; other cases are interleaved with acquires.)
*/
final void enqueue(Node node) {
if (node != null) {
for (;;) {
Node t = tail;
node.setPrevRelaxed(t); // avoid unnecessary fence
if (t == null) // initialize
tryInitializeHead();
else if (casTail(t, node)) {
t.next = node;
if (t.status < 0) // wake up to clean link
//喚醒線程
LockSupport.unpark(node.waiter);
break;
}
}
}
}