aba問題,描述的是乙個變數v,它的值經歷a -> b ->a的變化,導致看起來好像沒有變一樣,其實,第二次出現的a已經不是第一次出現的a了,是被修改過的。
下面復現aba問題,並解決
測試**:
public class abatest catch (interruptedexception e)
// 執行緒a看到的那個0,已經是被執行緒b修改過的0了(num目前的狀態0 - 1 - 0)
num.compareandset(0,2);
// stampedreference.compareandset("a", "c",1,2);
latch.countdown();
}).start();
new thread(() -> ).start();
try catch (interruptedexception e)
system.out.println("最終 num = "+num.get());
// stampedreference的值,沒有修改為c
// system.out.println("最終 stampedreference = "+stampedreference.getreference()+",stampedreference.getstamp()="+stampedreference.getstamp());
}
測試結果:
num 初始值為 0,執行緒a準備設定 num 為 2
num 初始值為 0,執行緒b 設定 num 為 1
num 初始值為 1,執行緒b 設定 num 為 0
最終 num = 2
結果說明:num是atomicinteger 型別的變數,保證其原子操作,但是並不能防止aba情況的出現:執行緒a第二次看到的0是被執行緒b修改回來的0,並不是第一次遇到的0。
stampedreference 初始值為 a,執行緒a準備將其設定為c
stampedreference 初始值為 a,執行緒b準備將其設定為b
stampedreference 初始值為 b,執行緒b準備將其設定為a
最終 stampedreference = a,stampedreference.getstamp()=3
可以看到,stampedreference 最終的值是a,也就是執行緒b第二次修改後的值,因為它的版本號為3,不是1。atomicstampedreference解決aba問題,在於它提供了乙個版本號,在進行cas操作時,不僅比較引用是否相等,還比較版本號和預期的是否一樣,兩者都一樣才會進行更新,請看原始碼:
/**
* atomically sets the value of both the reference and stamp
* to the given update values if the
* current reference is to the expected reference
* and the current stamp is equal to the expected stamp.
** @param expectedreference the expected value of the reference
* @param newreference the new value for the reference
* @param expectedstamp the expected value of the stamp
* @param newstamp the new value for the stamp
* @return if successful
*/public boolean compareandset(v expectedreference,
v newreference,
int expectedstamp,
int newstamp)
其中,stamp 可以看作是版本號,而pair物件只是對reference 和 stamp的包裝。 多執行緒原子性 CAS以及ABA問題
通常情況下為了保證安全,在乙個執行緒對乙個數值訪問時要上鎖,但是為了保證效率,cas中是不上鎖的。列如 現在有乙個值為0,讀取這個值,並且將其存在e中,則 e 0。然後對e進行遞增運算,有計算結果設為v。e 後,設乙個新的值為n 即 n e 這時去檢視e,如果e還是為0,則表明沒有其他的執行緒修改e...
多執行緒程式設計系列學習之 lock關鍵字
概念 lock 語句獲取給定物件的互斥 lock,執行語句塊,然後釋放 lock。持有 lock 時,持有 lock 的執行緒可以再次獲取並釋放 lock。阻止任何其他執行緒獲取 lock 並等待釋放 lock。lock 只適用單機情況,分布式和負債均衡可以考慮分布式鎖。形式lock this lo...
SpringCloud系列學習
在講解springcloud 之前,我們先講一講單體架構系統。所謂的單體架構就是所有功能,都放在乙個應用裡。比如後面要講的乙個單體產品服務應用,提供資料和檢視都在乙個springboot裡。單體架構系統有其好處,如便於開發,測試,部署也很方便,直接打成乙個 jar 或者 war,就什麼都好了。不過單...