面試必考AQS-AQS概覽

AQS介紹

AQS的含義

AQS是java.util.concurrent.locks.AbstractQueuedSynchronizer的簡稱,直譯就是“抽象隊列同步器”,它是java中大部分lock類的間接實現者。AQS中實現的各種邏輯非常精妙,在此膜拜一下Doug Lea老爺子。

剛剛有提到AQS間接實現了lock類,檢查java中提供的lock類,如ReentrantLock,ReentrantReadWriteLock,StampedLock,CountDownLatch,CyclicBarrier等,內部都有AQS的實現類,完成了不同邏輯來承載不同Lock的實現。

 

AQS的構成

查看源碼可知,大致有如下內容:

  • static final class Node {...} // 鏈表節點
  • public class ConditionObject implements Condition, java.io.Serializable {...} // 條件對象
  • private transient volatile Node head; // 鏈表頭
  • private transient volatile Node tail; // 鏈表尾
  • private volatile int state; // 資源
  • private static final Unsafe unsafe = Unsafe.getUnsafe();// 用於cas操作的變量
  • private static final long stateOffset,headOffset,tailOffset,waitStatusOffset,nextOffset; // 用於cas操作的變量
  • 一些實例方法操作鏈表及資源
  • 一些抽象方法等待被實現

 

AQS的由來

在AQS的源碼中,存在一個由head和tail構成的鏈表,在知曉它存在的作用前,先了解一下硬件領域的多核CPU架構。

從系統架構來看,目前的商用服務器大體可以分爲三類,即對稱多處理器結構 (SMP : Symmetric Multi-Processor) ,非一致存儲訪問結構 (NUMA : Non-Uniform Memory Access) ,以及海量並行處理結構 (MPP : Massive Parallel Processing) 。

 

處理器架構

SMP架構

即對稱多處理器結構,在這種架構中,一臺計算機由多個CPU組成,並共享內存和其他資源,所有的CPU都可以平等的訪問內存、I/O等。雖然可以同時使用多個CPU,但從外部表現來看,它們就如同一臺單CPU機器一樣,操作系統將任務隊列對稱地分佈於多個CPU之上,從而極大地提高了整個系統的數據處理能力。

日常的pc機,筆記本,手機還有一些老的服務器都是這個架構,其架構簡單,但是拓展性能非常差,從linux 上也能看到:

ls /sys/devices/system/node/# 如果只看到一個node0 那就是smp架構
 SMP架構圖示
 SMP架構圖示

但是隨着CPU數量的增加,每個CPU都要訪問共享資源,而資源在某些場景下只能單線程訪問,在某些場景下的操作又必須通知到其他CPU,那麼這就帶來了性能損耗、資源浪費,成爲了系統瓶頸。

 

NUMA架構

即非一致存儲訪問,這種模型的是爲了解決smp擴容性很差而提出的技術方案。它按組將CPU分爲多模塊,每個CPU模塊由多個CPU組成,並且具有獨立的本地內存、I/O等,模塊之間的訪問通過互聯模塊完成(類似遠程通信),訪問本地資源的速度會遠高於訪問外部資源。

NUMA架構圖示

 

NUMA架構相當於打包多個SMP架構的CPU,它能較好解決SMP架構存在的擴展問題;但是,在NUMA的單個CPU模塊中,雖然控制了CPU數量減少了共享資源的操作時的性能損耗,由於存在互聯模塊的工作,在CPU模塊增加時,並不能線性的增加系統性能。

 

MPP架構

MPP 提供了另外一種進行系統擴展的方式,它由多個 SMP 服務器通過一定的節點互聯網絡進行連接,協同工作,完成相同的任務,從用戶的角度來看是一個服務器系統。 其基本特徵是由多個 SMP 服務器(每個 SMP 服務器稱節點)通過節點互聯網絡連接而成,每個節點只訪問自己的本地資源(內存、存儲等),是一種完全無共享(Share Nothing)結構,因而擴展能力最好,理論上其擴展無限制,目前的技術可實現512個節點互聯,數千個 CPU。 實驗證明, SMP 服務器 CPU 利用率最好的情況是 2 至 4 個 CPU [1]

MPP架構圖示

 

可以將MMP理解爲刀片服務器,每個刀扇裏的都是一臺獨立SMP架構服務器,並且每個刀扇之間均有高性能的網絡設備進行交互,保證smp服務器之間的數據傳輸性能。MMP架構比較依賴管理系統的處理能力來保障通信。

 

鎖模型

CLH鎖模型

是一種基於單向鏈表的、高性能、公平的自旋鎖。申請加鎖的線程通過前驅節點(pre-node)的變量進行自旋。當pre-node解鎖後,當前節點會結束自旋並進行加鎖。

CLH模型的邏輯:

  1. locked == true 表示節點處於加鎖狀態或者等待加鎖狀態。
  2. locked == false 表示節點處於解鎖狀態。
  3. 基於線程當前節點的前置節點的鎖值(locked)進行自旋,前置節點的 locked == true 自旋;當前置節點解鎖時,設置locked == false,後繼節點(就是當前節點)監聽到false,結束自旋。
  4. 每個節點在解鎖時更新自己的鎖值(locked),在這一時刻,該節點的後置節點會結束自旋,並進行加鎖。
CLH模型的邏輯圖示

 

由於自旋過程中,監控的是前置節點的變量,因此在SMP架構的共享內存模式,能更好的提供性能。

 

MCS鎖模型

與CLH鎖模型的最大區別是,監控的是自己的節點變量,當前置節點解鎖後,會主動修改自己的節點變量狀態。這種模型解決的是CLH模型在NUMA架構上的不足:當前置節點存在於其他CPU模塊時,自旋會導致頻繁的調用互聯模塊。是將自旋調整到了節點自身,互聯模塊的調用只存在於前置節點解鎖的時刻。

MCS模型的邏輯:

  1. locked == false 標識節點處於加鎖狀態(沒有自旋)
  2. locked == true 標識節點處於等待狀態(自旋)
  3. 基於當前節點的鎖值(locked)進行自旋,locked == true 自旋;當前置節點解鎖時,修改後繼節點(就是當前節點)的 locked == false ,進而結束當前節點的自旋。
  4. 每個節點在解鎖時更新後繼節點的鎖值(locked),在這一刻,該節點的後置節點會結束自旋,並進行加鎖。

 

MCS模型的邏輯圖示

說了這麼多,其實是想說明AQS中的鏈表,是爲了實現上面的模型,它是針對CLH鎖模型的一個變種。後面詳細描述AQS中針對head和tail的操作,實際上就是在操作鏈表的入隊和出隊。所以說,AQS中的大部分方法,就是在實現CLH鎖模型的邏輯。

 

AQS的功能

根據AQS的名稱:抽象隊列同步器,可以直白的知曉,

  1. 它是抽象類,自然有抽象方法。
  2. 它是一個隊列同步器,這裏的隊列我們可以指定是個鏈表
  3. 同步器,則是通過對鏈表及資源的操作,達到同步指標的目的(注意是同步的指標,它不等同於同步)

對於第三點,之所以這樣說,還有由於抽象類這個原因,從整體去看AQS,它的作用並不是去定義同步,而是去實現了一個CLH模型,直白點講就是實現瞭如何操作隊列及資源,至於何時達到同步,是由實現類去決定的。

由此可知:

  1. AQS中的實例方法:自身實現的用於操作隊列以及資源。
  2. AQS中的抽象方法:交給子類實現,來決定同步狀態。

 

尾聲

本文只是簡略的介紹了AQS的組成及每個成員的功能後續內容將會詳細展開每個成員,深挖它們的內在邏輯。

 

推薦閱讀

面試必考AQS-AQS概覽

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章