JDK源碼分析-AbstractQueuedSynchronizer(1)

概述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.

相關文章
相關標籤/搜索