概述
前文「JDK原始碼分析-Lock&Condition」簡要分析了 Lock 介面,它在 JDK 中的實現類主要是 ReentrantLock (可譯為“重入鎖”)。ReentrantLock 的實現主要依賴於其內部的一個巢狀類 Sync,而 Sync 又繼承自 AbstractQueuedSynchronizer (簡稱 AQS)。而且,不僅 ReentrantLock,其他一些併發工具類如 CountdownLatch、CyclicBarrier 等,其實現也都是基於 AQS 類。AQS 可以理解為併發包中許多類實現的基石。因此,在分析併發包中常用類的實現原理前,有必要先理解一下 AQS,之後再分析的時候就會簡單不少。
AQS 內部有一個核心變數 state;此外,以 Node 類為節點維護了兩種佇列:主佇列(main queue)和條件佇列(condition queue),簡單起見,分別可以將二者理解為雙連結串列和單連結串列。
AQS 就像是提供了一套基礎設施的裝置,其它常用類如 ReentrantLock、CountdownLatch 等的內部巢狀類 Sync,都是在 AQS 提供的基礎設施之上制定了自己的“遊戲規則”,進而生產出了不同的產品。而它們的遊戲規則都是圍繞 state 變數和這兩種佇列進行操作的。
PS: 由於 AQS 內容較多,因此打算分多篇文章進行分析,本文先對其整體進行概述。
程式碼分析
AQS 類簽名:
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {}
可以看到它是一個抽象類,不能直接被例項化。它的父類 AbstractOwnableSynchronizer 的主要程式碼如下:
public abstract class AbstractOwnableSynchronizer implements java.io.Serializable { /** * The current owner of exclusive mode synchronization. */ private transient Thread exclusiveOwnerThread; // 其他程式碼 }
其內部主要維護了一個變數 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.
PS: 本文首發於微信公眾號【WriteOnRead】。