概述html
前文「JDK源碼分析-Lock&Condition」簡要分析了 Lock 接口,它在 JDK 中的實現類主要是 ReentrantLock (可譯爲「重入鎖」)。ReentrantLock 的實現主要依賴於其內部的一個嵌套類 Sync,而 Sync 又繼承自 AbstractQueuedSynchronizer (簡稱 AQS)。並且,不只 ReentrantLock,其餘一些併發工具類如 CountdownLatch、CyclicBarrier 等,其實現也都是基於 AQS 類。AQS 能夠理解爲併發包中許多類實現的基石。所以,在分析併發包中經常使用類的實現原理前,有必要先理解一下 AQS,以後再分析的時候就會簡單很多。java
AQS 內部有一個核心變量 state;此外,以 Node 類爲節點維護了兩種隊列:主隊列(main queue)和條件隊列(condition queue),簡單起見,分別能夠將兩者理解爲雙鏈表和單鏈表。node
AQS 就像是提供了一套基礎設施的設備,其它經常使用類如 ReentrantLock、CountdownLatch 等的內部嵌套類 Sync,都是在 AQS 提供的基礎設施之上制定了本身的「遊戲規則」,進而生產出了不一樣的產品。而它們的遊戲規則都是圍繞 state 變量和這兩種隊列進行操做的。安全
PS: 因爲 AQS 內容較多,所以打算分多篇文章進行分析,本文先對其總體進行概述。併發
代碼分析app
AQS 類簽名:工具
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {}
源碼分析
能夠看到它是一個抽象類,不能直接被實例化。它的父類 AbstractOwnableSynchronizer 的主要代碼以下:flex
public abstract class AbstractOwnableSynchronizer
implements java.io.Serializable {
/**
* The current owner of exclusive mode synchronization.
*/
private transient Thread exclusiveOwnerThread;
// 其餘代碼
}
ui
其內部主要維護了一個變量 exclusiveOwnerThread,做用是標記獨佔模式下的 Owner 線程,後面涉及到的時候再進行分析。
嵌套類
AQS 內部有兩個嵌套類,分別爲 Node 和 ConditionObject。
Node 類代碼以下:
static final class Node {
// 共享模式
static final Node SHARED = new Node();
// 獨佔模式
static final Node EXCLUSIVE = null;
// waitStatus的幾種狀態
static final int CANCELLED = 1;
static final int SIGNAL = -1;
static final int CONDITION = -2;
static final int PROPAGATE = -3;
volatile int waitStatus;
// 前驅節點(主隊列)
volatile Node prev;
// 後繼節點(主隊列)
volatile Node next;
// 節點的線程
volatile Thread thread;
// 後繼節點(條件隊列)
Node nextWaiter;
final boolean isShared() {
return nextWaiter == SHARED;
}
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
}
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 類能夠理解爲對線程 Thread 的封裝。所以,在主隊列中排隊的一個個節點能夠理解爲一個個有模式(mode)、有狀態(waitStatus)的線程。
嵌套類 ConditionObject:
public class ConditionObject implements Condition, java.io.Serializable {
/** First node of condition queue. */
private transient Node firstWaiter;
/** Last node of condition queue. */
private transient Node lastWaiter;
// ...
}
ConditionObject 實現了 Condition 接口,它主要操做的是條件隊列,這裏只貼了其類簽名和頭尾節點,後面用到的時候再具體分析。
主要變量
AQS 代碼雖長,但它的成員變量卻很少,以下:
// 主隊列頭節點
private transient volatile Node head;
// 主隊列尾結點
private transient volatile Node tail;
// 狀態,AQS 維護的一個核心變量
private volatile int state;
其中,head 和 tail 爲主隊列的頭尾節點,state 爲 AQS 維護的核心變量,ReentrantLock 等類中的 Sync 類實現,都是經過操做 state 來實現各自功能的。
CAS 操做
AQS 內部經過 Unsafe 類實現了一系列 CAS (Compare And Swap) 操做(有關 CAS 的概念這裏再也不詳解,可自行搜索瞭解):
// 獲取 Unsafe 實例
private static final Unsafe unsafe = Unsafe.getUnsafe();
// state、head、tail 等變量的內存偏移地址
private static final long stateOffset;
private static final long headOffset;
private static final long tailOffset;
private static final long waitStatusOffset;
private static final long 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) { throw new Error(ex); }
}
// 一些 CAS 操做
private final boolean compareAndSetHead(Node update) {
return unsafe.compareAndSwapObject(this, headOffset, null, update);
}
private final boolean compareAndSetTail(Node expect, Node update) {
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
private static final boolean compareAndSetWaitStatus(Node node,
int expect,
int update) {
return unsafe.compareAndSwapInt(node, waitStatusOffset,
expect, update);
}
private static final boolean compareAndSetNext(Node node,
Node expect,
Node update) {
return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
}
AQS 內部的許多操做是經過 CAS 來實現線程安全的。
小結
1. AQS 是一個抽象類,沒法直接進行實例化;
2. AQS 內部維護了一個核心變量 state,以及兩種隊列:主隊列(main queue)和條件隊列(condition queue);
3. AQS 提供了一套基礎設施,ReentrantLock 等類一般用一個內部嵌套類 Sync 繼承 AQS,並在 Sync 類中制定本身的「遊戲規則」。
本文僅對 AQS 作了概述,後面再詳細分析實現原理。此外,還有一個類 AbstractQueuedLongSynchronizer,它與 AQS 基本徹底同樣,區別在於前者的 state 變量爲 long 類型,而 AQS 爲 int 類型,再也不單獨進行分析。
PS: 有幾篇文章寫得也不錯,連接以下:
https://www.cnblogs.com/liuyun1995/p/8400663.html
Stay hungry, stay foolish.