併發容器J.U.C -- AQS元件(一)

eluanshi12發表於2018-12-26

AQS簡介

AQS全名:AbstractQueuedSynchronizer,是併發容器J.U.C(java.lang.concurrent)下locks包內的一個類。它實現了一個FIFO(FirstIn、FisrtOut先進先出)的佇列。底層實現的資料結構是一個雙向列表
AQS資料結構
Sync queue:同步佇列,是一個雙向列表。包括head節點和tail節點。head節點主要用作後續的排程。
Condition queue:非必須,單向列表。當程式中存在cindition的時候才會存在此列表。

AQS設計原理

  1. 使用Node實現FIFO佇列,可以用於構建或者其他同步裝置的基礎框架。
  2. 利用int型別標識狀態。在AQS類中有一個叫做state的成員變數(private volatile int state;),表示獲取鎖的執行緒數(state=0,表示還沒有執行緒獲取鎖,1表示有執行緒獲取了鎖。大於1表示重入鎖的數量)和一個同步元件ReentrantLock。
  3. 使用方法是繼承,基於模板方法。
  4. 子類通過繼承並通過實現它的方法管理其狀態(acquire和release方法操縱狀態)。
  5. 可實現排它鎖和共享鎖模式(獨佔、共享)。AQS的功能主要分為兩類:獨佔和共享。子類,要麼實現並使用了它的獨佔功能的api,要麼使用了共享鎖的功能,而不會同時使用兩套api,即便是最有名的子類ReentrantReadWriteLock也是通過兩個內部類讀鎖和寫鎖分別實現了兩套api來實現的。

可重入鎖,指對同一個ReentrantLock物件多次執行lock()加鎖和unlock()釋放鎖。

AQS實現思路

  1. AQS內部維護了一個CLH佇列來管理鎖。
  2. 執行緒會首先嚐試獲取鎖,如果失敗就將當前執行緒及等待狀態等資訊包裝成一個node節點加入到同步佇列sync queue裡。
  3. 不斷的重新嘗試獲取鎖(當前節點為head的直接後繼才會嘗試)。如果失敗就會阻塞自己,直到自己被喚醒。
  4. 當持有鎖的執行緒釋放鎖的時候,會喚醒佇列中的後繼執行緒。
    在這裡插入圖片描述

釋放鎖

喚醒,獲取鎖
圖片參考:大白話聊聊Java併發面試問題之談談你對AQS的理解?【石杉的架構筆記】

相關文章