六 多執行緒 CAS

2021-08-25 02:50:32 字數 2931 閱讀 2860

鎖的開銷極大。在某些場景,如保證乙個變數的 read-modify-write操作的原子性。這種場景可以通過使用cas解決而不需要用到鎖。

unsafe類中通過cas修改int型別變數原始碼。

/**

*var1 atomicinteger物件

*var2 記憶體偏移量

*var4 增加的值

*var5 獲取的變數原值,儲存在var5用於當預期值

*compareandswapint會比較記憶體值和var5相等的話就會改變記憶體值(即atomicintege * r物件中的變數)。

*/public final int getandaddint(object var1, long var2, int var4) while(!this.compareandswapint(var1, var2, var5, var5 + var4));

return var5;

}

原子變數

以上**是原子遍歷atomicinteger自增**的實現片段。jdk基於cas提供了保證共享變數read-modify-write操作原子性的類。

分組類名

基本型別

atomicinteger,atomiclong,atomicboolean

陣列型別

atomicintegerarray,atomiclongarray,atomicreferencearray

字段更新

atomicintegerfieldupdater,atomiclongfieldupdater,atomicreferencefieldupdater

引用型atomicreference,atomicstampedreference,atomicmarkablereference

atomicinteger

方法作用

int accumulateandget(int x, intbinaryoperator accumulatorfunction)

使用將給定函式應用於當前值和給定值的結果原子更新當前值,返回更新後的值。

int addandget(int delta)

將給定的值原子地新增到當前值。

boolean compareandset(int expect, int update)

如果當前值 ==為預期值,則將該值原子設定為給定的更新值。

int decrementandget()

原子減1當前值。

double doublevalue()

返回此值 atomicinteger為 double乙個寬元轉換後。

float floatvalue()

返回此值 atomicinteger為 float乙個寬元轉換後。

int get()

獲取當前值。

int getandaccumulate(int x, intbinaryoperator accumulatorfunction)

使用給定函式應用給當前值和給定值的結果原子更新當前值,返回上乙個值。

int getandadd(int delta)

將給定的值原子地新增到當前值。

int getanddecrement()

原子減1當前值。

int getandincrement()

原子上增加乙個當前值。

int getandset(int newvalue)

將原子設定為給定值並返回舊值。

int getandupdate(intunaryoperator updatefunction)

用應用給定函式的結果原子更新當前值,返回上乙個值。

int incrementandget()

原子上增加乙個當前值。

int intvalue()

將 atomicinteger的值作為 int 。

void lazyset(int newvalue)

最終設定為給定值。

long longvalue()

返回此值 atomicinteger為 long乙個寬元轉換後。

void set(int newvalue)

設定為給定值。

string tostring()

返回當前值的string表示形式。

int updateandget(intunaryoperator updatefunction)

使用給定函式的結果原子更新當前值,返回更新的值。

boolean weakcompareandset(int expect, int update)

如果當前值 ==為預期值,則將值設定為給定更新值。

#### aba問題 以上說到,cas是將預期值和記憶體當前值比較,通過比較結果來判斷其他執行緒是否修改過該變數。但是如果存在其他執行緒修改變數後又改回原值(即預期值),在某些場景就會存在問題。

aba問題例子

銀行賬戶 500元(共享變數)

要取出50元,機器故障傳送了2個請求a,b,此時兩個請求的期望值都是500,新值450

a請求執行完後,記憶體值變成450。所以第二個請求是不會成功的。

但是如果在b請求執行前,c又往賬戶存了50塊。這時銀行帳號變成500。b請求預期值滿足提交成功,銀行賬戶最終存款為 450。

這種情況下,存款少了50塊。

aba解決方案。

aba問題可以通過版本號來解決,每次修改操作都新增乙個版本號。例如剛才的取款操作加個版本號 1,在存款操作執行後版本號+1,變為2。取款的第二次請求執行時就會判斷版本號不是1,執行失敗。

aba問題,原子變數atomicstampedreference,atomicmarkablereference用於解決aba問題。

注意cas只能保證乙個共享變數的操作的原子性(原子性操作+原子性操作≠原子操作),如果要保持多個共享變數的操作的原子性,就必須使用鎖。

如果變數更新多次失敗,迴圈時間長開銷大。

aba問題

CAS機制(多執行緒)

當要更新乙個變數的時候,只有當變數的預期值a和記憶體位址v當中的實際值相同的時候,才會將記憶體位址v對應的值修改為b 舉個栗子 在乙個記憶體位址為v記憶體中,儲存著變數值10 即此時a 10 此時,來了乙個執行緒a,想對該變數進行增加1操作 即此時對執行緒a來說 a 10,b 11 但是,當執行緒a...

CAS在多執行緒方面的妙用

今天來教大家如何靈活使用cas 以atomicinteger為例子,凡是以cas思想實現的工具類,都具有 compareandset 舊值,新值 在多執行緒中,我們無法知道到底哪個執行緒會先執行,有的時候我們需要讓執行緒按順序執行,比如常見的面試題 給你三個執行緒,輸出10個abc這樣的字串 abc...

多執行緒六 dispatch semaphore

一 定義 訊號量的初始值為1,代表同時只允許1條執行緒訪問資源,保證執行緒同步 例子 執行緒10 7 6 9 8 void test dispatch time的宣告如下 dispatch time t dispatch time dispatch time t when,int64 t delta...