1. 程式人生 > 其它 >併發程式設計(六)抽象佇列同步器AQS解析

併發程式設計(六)抽象佇列同步器AQS解析

一、背景介紹

  學習AQS前先了解一位巨佬,也就是java.util.concurrent包的作者Doug Lea

  Java併發程式設計核心在於java.concurrent.util包,而JUC當中的大多數同步器實現都是圍繞著一些共同的基礎行為去實現的,比如:

  • 等待佇列
  • 條件佇列
  • 獨佔獲取
  • 共享獲取等

  定義:而這些行為的抽象就是基於AbstractQueuedSynchronizer簡稱AQS,AQS定義了一套多執行緒訪問共享資源的同步器框架,是一個依賴狀態【state:表示資源的可用狀態】的同步器。

  PS:AbstractQueuedSynchronizer位於java.util.concurrent.locks

包下,是一個抽象類,像我們常用的ReentrantLockCountDownLatch內部會對這個AbstractQueuedSynchronizer這個類進行繼承。

  PS:AQS底層有一個佇列容器來存放被阻塞的執行緒(用佇列的原因是因為要實現公平鎖的概念【排隊】)【AQS也是這個佇列的縮寫】

二、AQS具備特性

基本特性

  • 阻塞等待佇列
  • 共享/獨佔
  • 公平/非公平
  • 可重入
  • 允許中斷

框架實現思路

  • 1、定義內部類Sync繼承AQS
  • 2、將同步器所有呼叫都對映到Sync對應的方法

state三種訪問方式

  • getState()
  • setState()
  • compareAndSetState()

AQS定義兩種資源共享方式

  • Exclusive-獨佔:只有一個執行緒能執行,如ReentrantLock
  • Share-共享:多個執行緒可以同時執行,如Semaphore/CountDownLatch

三、AQS的兩種佇列

同步等待佇列

  同步等待佇列也稱CLH佇列【作者姓名字母縮寫】,是一種基於雙向連結串列資料結構的佇列,是FIFO先入先出執行緒等待佇列,由阻塞機制實現。

條件等待佇列

  佇列結構與上圖類似,就不重複贅述了。【condition條件佇列在後面會去學習】

四、Lock鎖內部的一些關鍵方法

isHeldExclusively()

  作用:判斷該執行緒是否正在獨佔資源。

  PS:只有用到condition才需要去實現它。

tryRelease(int state減少的量)【獨佔的鎖有對應的實現方法,如ReentrantLock】

  作用:嘗試釋放資源,成功則返回true,失敗則返回false。

tryAcquire(int state增加的量)【獨佔的鎖有對應的實現方法,如ReentrantLock】

  作用:嘗試獲取資源,成功則返回true,失敗則返回false。

tryAcquireShared(int)【共享的鎖有對應的實現方法,如CountDownLatch】

  作用:嘗試獲取共享鎖,實現方式和獨佔鎖類似。

  • 負數表示失敗
  • 正數表示成功,且有剩餘資源

  PS:state 狀態變數,state 的值代表著等待的執行緒數,比如初始化為 5,表示正在等待的執行緒數為 5,每次呼叫 countDown() 函式都會減1。

tryReleaseShared(int)【共享的鎖有對應的實現方法,如CountDownLatch】

  作用:嘗試釋放共享資源,如果釋放後允許喚醒後續 等待結點返回true,否則返回false。