深入理解Atomic原子類


Atomic是基於unsafe類自旋操作實現的,下面以AtomicInteger類為例進行講解。

要理解Atomic得先了解CAS

CAS

CAS全程Compare And Swap ,是條並發原語,功能是判斷內存中某個值是否與預期值相等,相等就用新值更新舊值,否則不更新。

Java中CAS是基於unsafe類實現的,所有的unsafe類中的方法都是native類修飾的,直接調用操作系統底層資源執行響應的任務。

unsafe.compareAndSwapInt(this, valueOffset, expect, update);

這是一條調用unsafe類中的compareAndSwapInt的方法,this表示當前對象,valueoffset表示當前對象的偏移地址,expect表示預期值

update表示更新值。作用是如果預期值和該對象偏移地址中的值一樣,就用更新值更新偏移地址中的值。

AtomicInteger類初始化

// setup to use Unsafe.compareAndSwapInt for updates
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;

    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    private volatile int value;

上述代碼是AtomicInteger類的默認參數初始化過程。其中value就是我們想要進行操作的那個值。加上volatile是為了

保證修改該值后立馬被其他線程感知到。

剛開始實例化unsafe類,這沒什么好說的,因為AtomicInteger類中方法都是通過unsafe類中方法來操作的。在靜態代碼塊中通過

unsafe.objectFieldOffset方法獲取value值的偏移量。也可以說是引用地址,以后通過該地址就可以隨時獲取value值和更改value值

AtomicInteger中方法的執行流程

這里我們以常用的getAndIncrement方法為例

/**
     * Atomically increments by one the current value.
     *
     * @return the previous value
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

可以看到,該方法是調用unsafe類中的getAndAddInt方法,繼續跟蹤該方法,進入unsafe類源代碼中

可以看到,調用unsafe類中getIntVolatile方法,方法參數var1為傳入的對象,即上述的AtomicInteger類的對象

var2為偏移地址,該方法的作用是通過該對象的偏移地址找到值,也就是找到上文的value值。(注意!這里已經

不是在AtomicInteger類源代碼中了而是進入了Unsafe類源代碼中,所以這里的this.getIntVolatile是unsafe類中的

getIntVolatile方法,該方法不是在AtomicInteger類中!)獲取到目前的value值后調用compareAndSwapInt方法,

使用獲取到的value值和當前當前對象地址偏移量中的值進行比較,如果相同就更新值,並且退出循環,否則就繼續

進入循環獲取該偏移地址中的最新值。為什么這里會導致使用var5 = getIntVolatile獲取偏移地址中的值后后面compareAndSwapInt

方法var5又會出現不等於偏移量地址上的值呢?按道理來說兩次獲取同一個偏移地址上的值是肯定會相同的,但是這里我們

考慮多線程的情況下,當兩個線程同時獲取當前偏移地址上的值,由於compareAndSwapInt是原子操作,所以必定有一個

線程會先執行完,並且改掉內存偏移地址上的值,那么另一個線程就會出現兩次獲取內存偏移地址上的值卻不一致的情況,

出現這種情況就需要重新獲取該值並且在此執行compareAndSwapInt,直到成功為止。

 

CAS與synchronized比較

CAS支持多個線程並發修改。並發程度高

synchronized一次只有一個線程修改,並發程度較低

CAS只支持一個共享變量的原子操作

synchronized可以對個變量進行加鎖

CAS會出現ABA問題


免責聲明!

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



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