aba問題,簡單描述就是存在乙個變數值為a,第乙個執行緒把變數值從a改成了b,第二個執行緒又把變數值從b改成了a,這樣,後面的執行緒讀取這個變數的時候就會以為變數值沒有發生過任何變化。
簡單用程式模擬一下:
public
class
abatest).
start()
;/**
* 執行緒2 2--->1
*/newthread((
)->).
start()
;/**
* 執行緒3
*/newthread((
)->
catch
(interruptedexception e)
int value = flag.
get();
if(value == inivalue)
latch.
countdown()
;}).
start()
;try
catch
(interruptedexception e)
}}
執行結果:
執行緒1更新flag:1--->2
執行緒2更新flag:2--->1
執行緒3發現原來flag的值從來沒有改變過啊,那我改變一下吧
執行緒3更新flag:1--->3
執行完成後flag:3
上述**簡單重現了一下aba問題,執行緒1和執行緒2都改變了值,但是由於兩個執行緒改變後的值和初始值一樣,導致執行緒3以為值從來沒有修改過。
解決方法,使用atomicstampedreference:
public
class
abasolvetest).
start()
;/**
* 執行緒2 2--->1
*/newthread((
)->).
start()
;/**
* 執行緒3
*/newthread((
)->
catch
(interruptedexception e)
int value = flag.
getreference()
;int stamp = flag.
getstamp()
;if(value == inivalue)
else
} latch.
countdown()
;}).
start()
;try
catch
(interruptedexception e)
}}
執行結果:
執行緒1更新flag:1--->2 時間戳:1001
執行緒2更新flag:2--->1 時間戳:1002
執行緒3發現flag的值雖然與初始值一樣,但時間戳與初始時間戳不同,有執行緒改變過了,我就不改變了,預期時間戳1000,當前時間戳1002
執行完成後flag:1
使用atomicstampedreference類,我們可以知道引用變數中途被更改了幾次,這樣就可以有效避免aba問題了。不過需要注意,如果時間戳重複,還是會出現aba的問題。
此外,還有一種解決方法使用,使用atomicmarkablereference類:
public
class
abasolvetest2).
start()
;/**
* 執行緒2 2--->1
*/newthread((
)->).
start()
;/**
* 執行緒3
*/newthread((
)->
catch
(interruptedexception e)
int value = flag.
getreference()
;boolean ismark = flag.
ismarked()
;if(value == inivalue)
else
} latch.
countdown()
;}).
start()
;try
catch
(interruptedexception e)
}}
執行結果:
執行緒1更新flag:1--->2 標示:true
執行緒2更新flag:2--->1 標示:true
執行緒3發現flag的值雖然與初始值一樣,標示與初始標識不同,有執行緒改變過了,我就不改變了,預期標示false,當前標示true
執行完成後flag:1
atomicmarkablereference使用boolean變數標示引用變數是否被更改過,這樣缺點很明顯,沒有atomicstampedreference使用靈活,因此只能用於某些特定情況下。 CAS的ABA問題詳解
aba問題 執行緒1搶先獲得cpu時間片,而執行緒2因為其他原因阻塞了,執行緒1取值與期望的a值比較,發現相等然後將值更新為b,然後這個時候出現了執行緒3,期望值為b,欲更新的值為a,執行緒3取值與期望的值b比較,發現相等則將值更新為a,此時執行緒2從阻塞中恢復,並且獲得了cpu時間片,這時候執行緒...
CAS的ABA問題詳解
在多執行緒場景下cas會出現aba問題,關於aba問題這裡簡單科普下,例如有2個執行緒同時對同乙個值 初始值為a 進行cas操作,這三個執行緒如下 1.執行緒1,期望值為a,欲更新的值為b 2.執行緒2,期望值為a,欲更新的值為b 執行緒1搶先獲得cpu時間片,而執行緒2因為其他原因阻塞了,執行緒1...
CAS下ABA問題及優化方案
2017年12月13日 21 47 03 helloworld搬運工 閱讀數 3365 標籤 資料庫 更多 一 併發業務場景 庫存業務,stock sid,num 其中 如上圖所示,兩個併發的查詢庫存操作,同時從資料庫都得到了庫存是5。接下來使用者發生了併發的庫存扣減動作 如上圖所示 這兩個設定庫存...