Java併發之CAS機制
引入
在單例項(一個JVM)環境下,多個執行緒併發操作某一共享資源時,我們可以通過synchronized同步鎖保證資源的可見性和原子性。但會存在效能問題:
(Synchronized關鍵字會讓沒有得到鎖資源的執行緒進入BLOCKED狀態,而後在爭奪到鎖資源後恢復為RUNNABLE狀態,這個過程中涉及到作業系統使用者模式和核心模式的轉換,代價比較高。
儘管Java1.6為Synchronized做了優化,增加了從偏向鎖到輕量級鎖再到重量級鎖的過度,但是在最終轉變為重量級鎖之後,效能仍然較低。)
我們可以使用原子類進行操作。在java.util.concurrent.atomic包下,一系列以Atomic開頭的包裝類。例如AtomicBoolean
Atomic操作類的底層正使用了CAS機制。
CAS是什麼
CAS是英文單詞Compare And Swap的縮寫,翻譯過來就是比較並替換。通過CPU指令級保證比較替換為一個原子操作。
CAS機制當中使用了3個基本運算元:記憶體地址V,舊的預期值A,要修改的新值B。
更新一個變數的時候,只有當變數的預期值A和記憶體地址V當中的實際值相同時,才會將記憶體地址V對應的值修改為B。
我們舉一個例子來說明CAS操作的機制:
1.在記憶體V中存在舊的預期值A=10
2.此時執行緒一想修改記憶體V中的值,新值B=11
3.但執行緒二搶先一步,記憶體V中的值被修改為11
4.線上程一準備修改時,先進行將舊的預期值A和此時的記憶體V中的值比較 A!=V,修改失敗
5.執行緒一重新獲得記憶體V值,此時A=11,B=12這個重新嘗試的過程叫自旋
6.執行緒一在次進行操作時,A=V,進行修改操作
7.執行緒一進行SWAP,修改V值為B
從思想上來說,Synchronized屬於悲觀鎖,悲觀地認為程式中的併發情況嚴重,所以嚴防死守。CAS屬於樂觀鎖,樂觀地認為程式中的併發情況不那麼嚴重,所以讓執行緒不斷去嘗試更新。