溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java原子操作類源碼分析

發(fā)布時間:2022-04-16 09:17:56 來源:億速云 閱讀:144 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“Java原子操作類源碼分析”,在日常操作中,相信很多人在Java原子操作類源碼分析問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java原子操作類源碼分析”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

我們先來看一下部分源碼:

public class AtomicLong extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 1927816293512124184L;

    //1.獲取Unsafe類實例
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    //2.存放value的偏移量
    private static final long valueOffset;
    static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();

    //3.用于判斷是否支持Long類型無鎖CAS
    private static native boolean VMSupportsCS8();

    static {
        try {
            //4.獲取value在AtomicLong中的偏移量
            valueOffset = unsafe.objectFieldOffset
                (AtomicLong.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
    //5.實際變量值
    private volatile long value;

    /**
     * Creates a new AtomicLong with the given initial value.
     *
     * @param initialValue the initial value
     */
    public AtomicLong(long initialValue) {
        value = initialValue;
    }
    ············省略部分代碼·············
}

上面代碼中,代碼1處通過Unsafe.getUnsafe()獲取到Unsafe類的實例(因為AtomicLong類是在rt.jar包下面的,AtomicLong類就是通過Bootstarp類加載器進行加載的)。代碼5處,value被聲明為volatile類型,保證內(nèi)存的可見性。通過代碼2,4獲取value變量在AtomicLong類中的偏移量。

接下來介紹一下AtomicLong中的主要函數(shù):

  • 遞增和遞減代碼

//調(diào)用unsafe方法,設(shè)置value=value+1后,返回原始的值
public final long getAndIncrement() {
    return unsafe.getAndAddLong(this, valueOffset, 1L);
}

//調(diào)用unsafe方法,設(shè)置value=value-1后,返回原始的值
public final long getAndDecrement() {
    return unsafe.getAndAddLong(this, valueOffset, -1L);
}


//調(diào)用unsafe方法,設(shè)置value=value+1后,返回遞增后的值
public final long incrementAndGet() {
    return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
}

//調(diào)用unsafe方法,設(shè)置value=value-1后,返回遞減后的值
public final long decrementAndGet() {
    return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L;
}

上面的四個函數(shù)內(nèi)部都是通過調(diào)用Unsafe的getAndAddLong方法來實現(xiàn)操作,這個函數(shù)是個原子性操作,這里第一個參數(shù)是AtomicLong實例的引用的,第二個參數(shù)是value變量在AtomicLong的偏移值,第三個參數(shù)是要設(shè)置的第二個變量的值。

其中g(shù)etAndIncrement()方法在JDK7中實現(xiàn)邏輯為:

public final long getAndIncrement() {
    while(true) {
        long current = get();
        long next = current + 1;
        if (compareAndSet(current, next))
            return current;
    }
}

如上代碼中,每個線程是先拿到變量的當(dāng)前值(由于value是volatile變量,所以這是獲取的最新值),然后在工作內(nèi)存中對其進行增1操作,而后使用CAS修改變量的值,如果設(shè)置失敗,則循環(huán)繼續(xù)嘗試,直到設(shè)置成功。

JDK8中的邏輯為:

public final long getAndIncrement() {
        retrturn unsafe.getAndAddLong(this, valueOffset, 1L);
    }

其中JDK8中的unsafe.getAndAddLong的代碼為:

public final long getAndAddLong(Object var1, long var2, long var4) {
   long var6;
   do {
       var6 = this.getLongVolatile(var1, var2);
   } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));

   return var6;
}

從中可以看到,JDK7中的AtomicLong中循環(huán)邏輯已經(jīng)被JDK8中的原子操作類Unsafe內(nèi)置了。

  • boolean compareAndSet(long expect,long update)

public final boolean compareAndSet(long expect,long update) 
{
    return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
}

函數(shù)在內(nèi)部調(diào)用了unsafe.compareAndSwapLong方法。如果原子變量中的value值等于expect,則使用update值更新該值并返回true,否則返回false。

到此,關(guān)于“Java原子操作類源碼分析”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI