1. 程式人生 > >Java CAS總結

Java CAS總結

發生 其他 text 修改 分析 引用 sso 允許 什麽

文章目錄

1、 CPU指令對CAS的支持(CPU的cas指令是原子的)

或許我們可能會有這樣的疑問,假設存在多個線程執行CAS操作並且CAS的步驟很多,有沒有可能在判斷V和E相同後,正要賦值時,切換了線程,更改了值。造成了數據不一致呢?答案是否定的,因為CAS是一種系統原語,原語屬於操作系統用語範疇,是由若幹條指令組成的,用於完成某個功能的一個過程,並且原語的執行必須是連續的,在執行過程中不允許被中斷,也就是說CAS是一條CPU的原子指令,不會造成所謂的數據不一致問題。

2、 並發包中的原子操作類(Atomic系列)

  通過前面的分析我們已基本理解了無鎖CAS的原理並對Java中的指針類Unsafe類有了比較全面的認識,下面進一步分析CAS在Java中的應用,即並發包中的原子操作類(Atomic系列),從JDK 1.5開始提供了java.util.concurrent.atomic

包,在該包中提供了許多基於CAS實現的原子操作類,用法方便,性能高效,主要分以下4種類型。

  可以發現AtomicInteger原子類的內部幾乎是基於前面分析過Unsafe類中的CAS相關操作的方法實現的,這也同時證明AtomicInteger是基於無鎖實現的,這裏重點分析自增操作實現過程,其他方法自增實現原理一樣。

3、 CAS的ABA問題及其解決方案

  假設這樣一種場景,當第一個線程執行CAS(V,E,U)操作,在獲取到當前變量V,準備修改為新值U前,另外兩個線程已連續修改了兩次變量V的值,使得該值又恢復為舊值,這樣的話,我們就無法正確判斷這個變量是否已被修改過,如下圖

技術分享圖片

這就是典型的CAS的ABA問題,一般情況這種情況發現的概率比較小,可能發生了也不會造成什麽問題,比如說我們對某個做加減法,不關心數字的過程,那麽發生ABA問題也沒啥關系。但是在某些情況下還是需要防止的,那麽該如何解決呢?在Java中解決ABA問題,我們可以使用以下兩個原子類

AtomicStampedReference類

  • AtomicStampedReference原子類是一個帶有時間戳的對象引用,在每次修改後,AtomicStampedReference不僅會設置新值而且還會記錄更改的時間。當AtomicStampedReference設置對象值時,對象值以及時間戳都必須滿足期望值才能寫入成功,這也就解決了反復讀寫時,無法預知值是否已被修改的窘境

參考文章:

1、JAVA中的CAS

Java CAS總結