Java中的CAS實現原理


一、什么是CAS?

    在計算機科學中,比較和交換(Conmpare And Swap)是用於實現多線程同步的原子指令。 它將內存位置的內容與給定值進行比較,只有在相同的情況下,將該內存位置的內容修改為新的給定值。 這是作為單個原子操作完成的。 原子性保證新值基於最新信息計算; 如果該值在同一時間被另一個線程更新,則寫入將失敗。 操作結果必須說明是否進行替換; 這可以通過一個簡單的布爾響應(這個變體通常稱為比較和設置),或通過返回從內存位置讀取的值來完成(摘自維基本科)

    JAVA1.5開始引入了CAS,主要代碼都放在JUC的atomic包下,如下圖:

  

 

 

二、JAVA中如何實現CAS操作

    以比較簡單的AtomicInteger為例,我們看一下都有哪些方法:

    從圖中可以看出JAVA中的CAS操作都是通過sun包下Unsafe類實現,而Unsafe類中的方法都是native方法,由JVM本地實現,筆者為了弄清楚真正的實現原理,查看了openJDK7的源碼,下面就稍作分析:

  

  

    Unsafe中對CAS的實現是C++寫的,從上圖可以看出最后調用的是Atomic:comxchg這個方法,這個方法的實現放在hotspot下的os_cpu包中,說明這個方法的實現和操作系統、CPU都有關系,我們以linux的X86處理器的實現為例來進行分析

    Linux的X86下主要是通過cmpxchgl這個指令在CPU級完成CAS操作的,但在多處理器情況下必須使用lock指令加鎖來完成。從這個例子就可以比較清晰的了解CAS的底層實現了,當然不同的操作系統和處理器的實現會有所不同,大家可以自行了解。

 

 

三、CAS在JUC中的運用

    我們看一下JUC中非常重要的一個類AbstractQueuedSynchronizer,作為JAVA中多種鎖實現的父類,其中有很多地方使用到了CAS操作以提升並發的效率

  

上圖為同步隊列的入隊操作,也是一種樂觀鎖的實現,多線程情況下,操作頭節點和尾節點都有可能失敗,失敗后會再次嘗試,直到成功。

 

 

四、ABA問題

  CAS可以有效的提升並發的效率,但同時也會引入ABA問題。

  如線程1從內存X中取出A,這時候另一個線程2也從內存X中取出A,並且線程2進行了一些操作將內存X中的值變成了B,然后線程2又將內存X中的數據變成A,這時候線程1進行CAS操作發現內存X中仍然是A,然后線程1操作成功。雖然線程1的CAS操作成功,但是整個過程就是有問題的。比如鏈表的頭在變化了兩次后恢復了原值,但是不代表鏈表就沒有變化。

  所以JAVA中提供了AtomicStampedReference/AtomicMarkableReference來處理會發生ABA問題的場景,主要是在對象中額外再增加一個標記來標識對象是否有過變更。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM