亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

AQS 原理

1. 前言

本節內容主要是對 AQS 原理的講解,之所以需要了解 AQS 原理,是因為后續講解的 ReentrantLock 是基于 AQS 原理的。本節內容相較于其他小節難度上會大一些,基礎薄弱的學習者可以選擇性學習本節內容或者跳過本節內容。

  • 了解什么是 AQS,這是認識 AQS 原理的前提,是本節的基礎知識點;
  • 了解 AQS 提供的兩種鎖功能,對其有一個全局的了解;
  • 了解 AQS 的內部框架原理結構,這是本節課程的核心所在,其他所有的知識點講解都是圍繞這一知識點的;
  • 釋放鎖以及添加線程對于 AQS 內部的變化,這是本節課程的重點知識,了解隊列的學習者能夠更快的掌握這部分知識;
  • AQS 與 ReentrantLock 的聯系,這是本節課程與 ReentrantLock 之間的過度知識。

2. 什么是 AQS

定義:AbstarctQueuedSynchronizer 簡稱 AQS,是一個用于構建鎖和同步容器的框架。

事實上 concurrent 包內許多類都是基于 AQS 構建的,例如 ReentrantLock,ReentrantReadWriteLock,FutureTask 等。AQS 解決了在實現同步容器時大量的細節問題。

圖片描述

AQS 使用一個 FIFO 隊列表示排隊等待鎖的線程,隊列頭結點稱作 “哨兵節點” 或者 “啞結點”,它不與任何線程關聯。其他的節點與等待線程關聯,每個階段維護一個等待狀態 waitStatus。

3. AQS 提供的兩種功能

從使用層面來說,AQS 的鎖功能分為兩種:獨占鎖和共享鎖。

獨占鎖:每次只能有一個線程持有鎖,比如前面給大家演示的 ReentrantLock 就是以獨占方式實現的互斥鎖;
共享鎖:允許多個線程同時獲取鎖,并發訪問共享資源,比如 ReentrantReadWriteLock。

4. AQS 的內部實現

AQS 的實現依賴內部的同步隊列,也就是 FIFO 的雙向隊列,如果當前線程競爭鎖失敗,那么 AQS 會把當前線程以及等待狀態信息構造成一個 Node 加入到同步隊列中,同時再阻塞該線程。當獲取鎖的線程釋放鎖以后,會從隊列中喚醒一個阻塞的節點 (線程)。

如下圖所示,一個節點表示一個線程,它保存著線程的引用(thread)、狀態(waitStatus)、前驅節點(prev)、后繼節點(next),其實就是個雙端雙向鏈表,其數據結構如下:
圖片描述

Tips:AQS 隊列內部維護的是一個 FIFO 的雙向鏈表,這種結構的特點是每個數據結構都有兩個指針,分別指向直接的后繼節點和直接前驅節點。所以雙向鏈表可以從任意一個節點開始,很方便的訪問前驅和后繼。每個 Node 其實是由線程封裝,當線程爭搶鎖失敗后會封裝成 Node 加入到 ASQ 隊列中去。

5. 添加線程對于 AQS 隊列的變化

當出現鎖競爭以及釋放鎖的時候,AQS 同步隊列中的節點會發生變化,首先看一下添加線程的場景。

圖片描述

這里會涉及到兩個變化

  • 隊列操作的變化:新的線程封裝成 Node 節點追加到同步隊列中,設置 prev 節點以及修改當前節點的前置節點的 next 節點指向自己;
  • tail 指向變化:通過同步器將 tail 重新指向新的尾部節點。

6. 釋放鎖移除節點對于 AQS 隊列的變化

第一個 head 節點表示獲取鎖成功的節點,當頭結點在釋放同步狀態時,會喚醒后繼節點,如果后繼節點獲得鎖成功,會把自己設置為頭結點,節點的變化過程如下:

圖片描述

這個過程也是涉及到兩個變化:

head 節點指向:修改 head 節點指向下一個獲得鎖的節點;
新的獲得鎖的節點:如圖所示,第二個節點被 head 指向了,此時將 prev 的指針指向 null,因為它自己本身就是第一個首節點,所以 pre 指向 null。

7. AQS 與 ReentrantLock 的聯系

ReentrantLock 實現:ReentrantLock 是根據 AQS 實現的獨占鎖,提供了兩個構造方法如下:

 public ReentrantLock() {
        sync = new NonfairSync();
    }
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

ReentrantLock 有三個內部類:Sync,NonfairSync,FairSync,繼承關系如下:
圖片描述

總結:我們可以看到,這三個內部類都是基于 AQS 進行的實現,由此可見,ReentrantLock 是基于 AQS 進行的實現。

ReentrantLock 提供兩種類型的鎖:公平鎖,非公平鎖。分別對應 FairSync,NonfairSync。默認實現是 NonFairSync。

8. 小結

本節內容為 AQS 原理進行講解,會涉及到一些原理問題,隊列問題,基礎薄弱的學習者可以跳過或者選看本節內容,不會影響后續課程的學習。本節內容其實主要為了提供原理性的知識,對本節的知識掌握,使我們不僅僅是一個使用者。