多執行緒實戰 一 通過AQS實現乙個自定義同步鎖

2021-10-07 09:19:49 字數 3336 閱讀 7136

1. 什麼是 aqs ?

2. 如何通過aqs實現乙個自定義的鎖?

3. reentrantlock如何實現 可重入以及公平/非公平鎖?

aqs(abstractqueuedsynchronizer)抽象佇列同步器,是併發大神doug lea設計出的用來快速實現同步需求的基礎元件。其通過乙個int 型別的state成員來表示同步狀態,通過乙個fifo的佇列來儲存等待獲取資源的執行緒的排隊工作。

其設計使用模板的設計模式,使用者一般可以通過實現乙個靜態內部類繼承aqs並實現其抽象方法即可。同步器沒有定義任何實現同步的方法,僅僅是定義了一些同步狀態的獲取以及釋放的方法來供同步器內部使用。

aqs同步器簡化了同步元件的實現,遮蔽了同步狀態的管理,執行緒排隊以及等待與喚醒這些底層操作。使開發者實現自定義的同步元件只專注於自己的邏輯,而無需關心這些通用的底層邏輯。

自定義同步器實現的時候主要實現下面幾種方法:

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

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

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

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

boolean tryreleaseshared(int args):共享方式。嘗試釋放資源,如果釋放後允許喚醒後續等待結點返回true,否則返回false。

這裡推薦一篇文章,詳細介紹了aqs底層實現,感興趣的同學可以深入了解下。

1. 需求

需求:設計乙個同步元件,同一時刻可以有n個執行緒同時進行訪問,超過n個的訪問將被阻塞。

2. 分析

首先,確定訪問模式,同一時刻可以有n個執行緒獲取到鎖,所以為共享式訪問,需要實現同步器提供的**tryacquireshared(int args)以及tryreleaseshared(int args)**方法。其次,要確定資源數,n個執行緒同時訪問,可以設定初始狀態state為n,當乙個執行緒獲取鎖時status減1,該執行緒釋放時,state加1.當狀態state為0時,表明所有同步資源已被獲取,其他再來訪問的執行緒只能被阻塞。同時設定狀態時使用aqs提供的compareandsetstate(int expect, int update)來保證原子性。

3.**實現

/**

* 自定義同步元件mutilock,允許同一時刻有capacity個執行緒獲取到鎖,超過capacity個執行緒的訪問將被阻塞。

* * @author tr.wang

*/public class mutilock

//靜態內部類,重寫tryacquireshared()以及tryreleaseshared()方法

private static class sync extends abstractqueuedsynchronizer

super.setstate(count);

}public int tryacquireshared(int reducecount) }}

public boolean tryreleaseshared(int returncount) }}

}public void lock()

public void unlock()

}

對其進行測試

/**

* twinslock測試,定義mutilock的容量為2,可以看出執行緒成對的輸出,一次只能有兩個執行緒獲取到鎖。

*/public class mutilocktest catch (interruptedexception e) finally

}});

thread.setdaemon(true);

thread.start();

}//每隔一秒換一行

for (int i = 0; i < 10; i++)

}}//輸出

當前執行緒名:thread-0

當前執行緒名:thread-1

當前執行緒名:thread-1

當前執行緒名:thread-0

當前執行緒名:thread-1

當前執行緒名:thread-0

當前執行緒名:thread-0

當前執行緒名:thread-1

當前執行緒名:thread-1

當前執行緒名:thread-0

通過上面的例子我們可以看出,使用aqs只需要實現簡單地抽象方法即可實現我們想要的同步元件,執行緒的排隊以及等待及喚醒都由aqs幫我們進行處理了。

我們常見的可重入以及公平、非公平鎖通過aqs有是如何實現的呢?我們可以看下reentrantlock的原始碼,看看其實如何實現可重入以及公平/非公平

1. 可重入

可重入指的是當前執行緒獲取到鎖之後能夠再次獲取該鎖而不被阻塞。

//非公平獲取

final boolean trylock()

//注意這裡

} else if (getexclusiveownerthread() == current)

return false;

}//非公平釋放

protected final boolean tryrelease(int releases)

2 公平/非公平
如果乙個鎖是公平的,那麼鎖的獲取順序滿足請求時間絕對順序,也就是fifo。

final boolean initialtrylock() 

} else if (getexclusiveownerthread() == current)

return false;

}

【多執行緒實戰 二】-同步工具類countdownlatch實現乙個程式啟動檢查服務

C 中線程的使用(一) 通過委託開啟乙個執行緒

整理一下關於c 中線程的使用方法,這裡講的是使用委託開啟執行緒,含有返回值的方法,用func開啟執行緒 還是直接看 吧 using system using system.collections.generic using system.linq using system.text using sy...

一 通過 npm yarn 構建vue專案

環境要求 node.js vue vue cli 注意 md xx 建立xx資料夾 cd xx 進入xx資料夾 cd 返回上一級 g 是全域性的意思 install 安裝 uninstall 解除安裝 init 初始化 webpack 壓縮 一 通過 npm 構建vue專案 1 檢視nodejs版本...

賽車遊戲 一 通過藍芽實現兩個手機互動

這個例子是與 賽車遊戲 二 的例子相聯絡的,並通過藍芽實現人機互動。想執行這個應用程式,你需要兩個藍芽終端手機 例如 索尼愛立信 k750 並在啟動程式前連線這兩個手機。一旦通訊被建立,3d世界將啟動,每個玩家會看見兩輛賽車 他自己和對手。在 3d世界中,每位選手可以使用手機軟鍵來操縱他自己的賽車。...