Java並發編程(2) AbstractQueuedSynchronizer的基本結構

來源:互聯網
上載者:User

標籤:名稱   同步隊列   public   table   接下來   blank   喚醒   java   包含   

一 前言  

  雖然已經有很多前輩已經分析過AbstractQueuedSynchronizer(簡稱AQS)類,但是感覺那些點始終是別人的,看一遍甚至幾遍終不會印象深刻。所以還是記錄下來印象更深刻,還能和大家一起探討(這就是重複造輪子的好處,另外也主要是這篇篇幅太長了,猶豫了好久才決定寫作)。既然有很多前輩都分析過這個類說明它是多麼的重要,下面我們看下concurrent包的實現就清楚AQS的所佔有的地位了。

二、AQS的內部結構

  個人習慣喜歡先看其內部結構,因為內部結果是一個類實現的核心。經過分析得知:AQS類底層的資料結構是使用雙向鏈表,包括head結點和tail結點,head結點主要用作後續的調度。另外還包含一個單向鏈表,只有當使用Condition時,才會存在此單向鏈表。並且可能會有多個Condition 鏈表(其中鏈表是隊列的一種具體表現,所以也可稱作隊列)。如:

三 內部結構源碼解析3.1 類的繼承關係

  

  1、說明它是一個抽象類別,就說明它可能存在抽象方法需要子類去重寫實現(具體有哪些方法需要重寫後續會說明)。

  2、它還繼承了AbstractOwnableSynchronizer(簡稱AOS)類可以設定獨佔資源線程和擷取獨佔資源線程(獨佔鎖會涉及到,AOS的源碼自己可以進去看看)。

  另外建議各位多看看類上的注釋,其實還蠻有作用的。

3.2 類的內部類

   先分析內部類中的結構再看AQS是怎麼引用它的。下面先看Node.class,主要分析都在注釋上了。

/** * Wait queue node class. * 注意看類上的注釋,上面是原注釋的第一行,表示等待隊列節點類(雖然實際上是一個雙向鏈表)。 */static final class Node {    /**     * 總共分為兩者模式:共用和獨佔     */    /** 在共用模式中等待的節點 */    static final Node SHARED = new Node();    /** 在獨佔模式中等待的節點 */    static final Node EXCLUSIVE = null;    /**     * 下面幾個表示節點狀態,也就是waitStatus所具有可能的值。     */    /**     * 標記線程處於取消狀態     * 節點進入該狀態就不會變化。     * /    static final int CANCELLED =  1;    /**     * 標記後繼節點的線程處於等待狀態,需要被取消停放(即被喚醒unpark)。     * 變化情況:噹噹前節點的線程如果釋放了同步狀態或者被取消,將會通知後繼節點,使後繼節點的線程得以運行。     */    static final int SIGNAL    = -1;    /**     * 標記線程正在等待條件(Condition),也就是該節點處於等待隊列中。     * 變化情況:當其他線程對Condition調用了signal()方法後,該節點將會從等待隊列中轉移到同步隊列中,加入到同步狀態的擷取中。     */    static final int CONDITION = -2;    /**     * 表示下一次共用式同步狀態擷取將會無條件的被傳播下去。     */    static final int PROPAGATE = -3;    /**     * 節點狀態,包含上面四種狀態(另外還有一種初始化狀態0)     * 特別注意:它是volatile關鍵字修飾的,保證對其線程可見度,但是不保證原子性。     * 所以更新狀態時,採用CAS方式去更新, 如:compareAndSetWaitStatus     */    volatile int waitStatus;    /**     * 前驅節點,比如當前節點被取消,那就需要前驅節點和後繼節點來完成串連。     */    volatile Node prev;    /**     * 後繼節點。     */    volatile Node next;    /**     * 入隊列時的當前線程。     */    volatile Thread thread;    /**     * 儲存condition隊列中的後繼節點。     */    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節點,放入隊列中。每個節點都包含了當前節點對應的線程、狀態、前置節點引用、後繼節點引用以及下一個等待者。

  其中還需要注意的是waitStatus對應的各個狀態代表著什麼意思,另外不清楚volatile關鍵字作用的請前去閱讀下。

屬性名稱 描述
int waitStatus 表示節點的狀態。其中包含的狀態有:
  1. CANCELLED,值為1,表示當前的線程被取消;節點進入該狀態就不會變化。
  2. SIGNAL,值為-1,表示當前節點的後繼節點包含的線程需要運行,也就是unpark;變化情況:噹噹前節點的線程如果釋放了同步狀態或者被取消,將會通知後繼節點,使後繼節點的線程得以運行。
  3. CONDITION,值為-2,表示當前節點在等待condition,也就是在condition隊列中;變化情況:當其他線程對Condition調用了signal()方法後,該節點將會從等待隊列中轉移到同步隊列中,加入到同步狀態的擷取中。
  4. PROPAGATE,值為-3,表示當前情境下後續的acquireShared能夠得以執行;
  5. 值為0,表示當前節點在sync隊列中,等待著擷取鎖。
Node prev
前驅節點,比如當前節點被取消,那就需要前驅節點和後繼節點來完成串連。
Node next
後繼節點。
Thread thread
入隊列時的當前線程。
Node nextWaiter
儲存condition隊列中的後繼節點。

  接下來簡單看看ConditionObject的源碼,後續我們會單獨分析下這個類的作用。

/** * 實現Condition介面 */public class ConditionObject implements Condition, java.io.Serializable {    private static final long serialVersionUID = 1173984872572414699L;    /**     * 條件隊列的第一個節點。     */    private transient AbstractQueuedSynchronizer.Node firstWaiter;    /**     * 條件隊列的最後一個節點。     */    private transient AbstractQueuedSynchronizer.Node lastWaiter;}

  從中可以看它還是實現了Condition介面,而Condition介面又定義了什麼規範呢?自己去看:),你會不會發現有點跟Object中的幾個方法類似呢。

3.3 主要內部成員
    // 頭結點    private transient volatile Node head;    // 尾結點    private transient volatile Node tail;    // 同步狀態    private volatile int state;
四、總結

  通過上述分析就很清楚其內部結構是什麼了吧。總結下:

  節點(Node)是成為sync隊列和condition隊列構建的基礎,在同步器中就包含了sync隊列(Node雙向鏈表)。同步器擁有三個成員變數:sync隊列的頭結點head、sync隊列的尾節點tail和狀態state。對於鎖的擷取,請求形成節點,將其掛載在尾部,而鎖資源的轉移(釋放再擷取)是從頭部開始向後進行。對於同步器維護的狀態state,多個線程對其的擷取將會產生一個鏈式的結構。

 

Java並發編程(2) AbstractQueuedSynchronizer的基本結構

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.