天天看點

【JDK】JDK源碼分析-AbstractQueuedSynchronizer(1)

概述

前文「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 類型,不再單獨進行分析。