併發程式設計之AQS的同步原理

2021-09-22 21:29:26 字數 2202 閱讀 1160

aqs(abstractqueuedsynchronizer),抽象佇列同步器。

aqs的同步狀態

aqs使用乙個int成員變數來表示同步狀態,通過內建的fifo佇列來完成獲取資源執行緒的排隊工作。aqs使用cas對該同步狀態進行原子操作實現對其值的修改。

private volatile int state;//共享變數,使用volatile修飾保證執行緒可見性
狀態資訊通過getstate,setstate,compareandsetstate方法進行操作

//返回同步狀態的當前值

protected final int getstate()

// 設定同步狀態的值

protected final void setstate(intnewstate)

//原子地(cas操作)將同步狀態值設定為給定值update如果當前同步狀態的值等於expect(期望值)

protected final boolean compareandsetstate(intexpect, intupdate)

aqs內部的同步佇列

同步器aqs內部的實現是依賴同步佇列(雙向佇列)來完成同步狀態的管理。

當前執行緒獲取資源失敗時,同步器aqs會將當前執行緒和等待狀態等資訊構造成為乙個節點(node)加入到同步佇列,同時會阻塞當前執行緒;

當同步狀態釋放的時候,會把佇列首節點(或者其他節點,取決於是否是公平鎖)中的執行緒喚醒,使首節點的執行緒再次嘗試獲取同步狀態。

節點的主要狀態有:waitstatus:等待狀態;prev:前驅節點;next:後繼節點;thread:當前節點代表的執行緒。

node加入佇列尾部的過程要保證執行緒的安全,否則在多執行緒的環境下,可能造成新增到佇列等待的節點順序錯誤,或者數量不對。因此同步器提供了cas操作,原子的設定尾節點(保證乙個未獲取到同步狀態的執行緒加入到同步佇列後,下乙個未獲取的執行緒才能夠加入)。

aqs定義兩種資源共享方式

share(共享):多個執行緒可同時執行,如semaphore/countdownlatch。semaphore、countdownlatch、 cyclicbarrier、readwritelock我們都會在後面講到。

aqs使用了模板方法模式,自定義同步器時需要重寫下面幾個aqs提供的模板方法:

isheldexclusively()//該執行緒是否正在獨佔資源。只有用到condition才需要去實現它。

tryacquire(int)//獨佔方式。嘗試獲取資源,成功則返回true,失敗則返回false。

tryrelease(int)//獨佔方式。嘗試釋放資源,成功則返回true,失敗則返回false。

tryacquireshared(int)//共享方式。嘗試獲取資源。負數表示失敗;0表示成功,但沒有剩餘可用資源;正數表示成功,且有剩餘資源。

tryreleaseshared(int)//共享方式。嘗試釋放資源,成功則返回true,失敗則返回false。

以reentrantlock為例,state初始化為0,表示未鎖定狀態。a執行緒lock()時,會呼叫tryacquire()獨佔該鎖並將state+1。此後,其他執行緒再tryacquire()時就會失敗,直到a執行緒unlock()到state=0(即釋放鎖)為止,其它執行緒才有機會獲取該鎖。當然,釋放鎖之前,a執行緒自己是可以重複獲取此鎖的(state會累加),這就是可重入的概念。但要注意,獲取多少次就要釋放多麼次,這樣才能保證state是能回到零態的。

再以countdownlatch以例,任務分為n個子執行緒去執行,state也初始化為n(注意n要與執行緒個數一致)。這n個子執行緒是並行執行的,每個子執行緒執行完後countdown()一次,state會cas(compare and swap)減1。等到所有子執行緒都執行完後(即state=0),會unpark()主呼叫執行緒,然後主呼叫執行緒就會從await()函式返回,繼續後余動作。

一般來說,自定義同步器要麼是獨佔方法,要麼是共享方式,他們也只需實現tryacquire-tryreleasetryacquireshared-tryreleaseshared中的一種即可。

但aqs也支援自定義同步器同時實現獨佔和共享兩種方式,如reentrantreadwritelock

併發程式設計之AQS中的CLH佇列

在aqs類檔案的開頭,作者新增了很長一段注釋,向開發者解釋clh佇列,以及aqs對clh佇列的使用。aqs裡面的clh佇列是clh同步鎖的一種變形。其主要從兩方面進行了改造 節點的結構與節點等待機制。在結構上,aqs類引入了頭結點和尾節點,他們分別指向佇列的頭和尾,嘗試獲取鎖 入佇列 釋放鎖等實現都...

Java併發之AQS原理詳解

一 abstractqueuedsynchronizer 的用途 下面簡稱 aqs,jdk 1.8 aqs是借助 fifo等待佇列,用來實現同步器的同步框架,通俗的來說,它是用來實現鎖的工具,一般來說,它需要實現這些功能 二 aqs 的工作原理 aqs的核心是基於鍊錶實現的 fifo等待佇列,該佇列...

java併發程式設計的藝術(六) AQS

aqs是佇列同步器 abstractqueuesynchronizer 是用來構建鎖和完成其他同步元件的基本框架,再lock裡面,很多的方法都將用到aqs以獲取同步狀態,實現鎖的語義,而不是依靠傳統的synchronized中的物件進行鎖獲取與釋放。aqs的核心思想是基於volatile int s...