Java多线程之CAS深入解析
Java多線程之CAS深入解析
目錄:
引子:螞蟻花唄一面:講一講AtomicInteger,為什么要用CAS而不是synchronized?
1. CAS是什么
CAS的全稱為Compare-And-Swap,它是一條CPU并發原語。
它的功能是判斷內存某個位置的值是否為期望值,如果是則更改為新的值,這個過程是原子的。
CAS并發原語體現在JAVA語言中就是sun.misc.Unsafe類中的CAS方法,JVM會幫我們實現CAS匯編指令。這是一種完全依賴于硬件的功能,通過它實現了原子操作。再次強調,由于CAS是一種系統原語,原語屬于操作系統用語范疇范,是由若干條指令組成的,用于完成某個功能的一個過程,并且原語的執行必須是連續的,在執行過程中不允許被中斷,也就說CAS是一條CPU的原了指令,不會造成所謂的數據不一致問題。
簡單測試代碼:
public class CASDemo {public static void main(String[] args) {AtomicInteger atomicInteger = new AtomicInteger(5);// main do thingSystem.out.println(atomicInteger.compareAndSet(5, 6)+"current data:"+atomicInteger.get());System.out.println(atomicInteger.compareAndSet(5, 2019)+"current data:"+atomicInteger.get());} }編譯結果:
2. CAS底層原理Unsafe深入解析
Unsafe是CAS的核心類,由于Java方法無法直接訪問底層系統,需要通過本地(native)方法來訪問,Unsafe相當于一個后門,基于該類可以直接操作特定內存的數據。Unsafe類存在于sun.misc包中,其內部方法操作可以像C的指針一樣直接操作內存,因為Java中CAS操作的執行依賴于Unsafe類的方法。
注意Unsafe類中的所有方法都是native修飾的,也就是Unsafe類中的方法都直接調用操作系統底層資源執行相應任務。
原子整型在i++中操作多線程環境下不需要加synchronized,也能保證線程安全,是因為它用的是Unsafe類,源代碼如下:
源碼解析,圖如下
解析:getAndAddInt()方法底層調用的是unsafe,傳三個參數,當前對象,內存地址偏移量,增量1,底層調用的是CAS思想,如果比較成功+1,失敗再重新獲得比較一次,直至成功為止。
假設線程A和線程B兩個線程同時執行getAndAddInt操作(分別跑在不同CPU上):
Atomiclnteger里面的value原始值為3,即主內存中Atomiclnteger的value為3,根據JMM模型,線程A和線程B各自持有一份值為3的value的副本分別到各自的工作內存。
線程A通過getIntVolatile(var1,var2)拿到value值3,這時線程A被掛起。
線程B也通過getIntVolatile(var1,var2)方法獲取到value值3,此時剛好線程B沒有被掛起并執行compareAndSwaplnt方法
比較內存值也為3,成功修改內存值為4,線程B打完收工,一切OK
這時線程A恢復,執行compareAndSwaplnt方法比較,發現自己手里的值數字3和主內存的值數字4不一致,說明該值己
經被其它線程搶先一步修改過了,那A線程本次修改失,只能重新讀取重新來一遍了。
線程A重新獲取value值,因為變量value被volatile修飾,所以其它線程對它的修改,線程A總是能夠看到,線程A繼續執
行compareAndSwaplnt進行比較替換,直到成功。
3. CAS缺點
篇幅原因,新開了一個博客文章進行解析,請看:
Java基礎之CAS缺點
總結
以上是生活随笔為你收集整理的Java多线程之CAS深入解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java多线程之单例模式在多线程环境下的
- 下一篇: Java多线程之CAS缺点