AtomicInteger

LZC發表於2020-08-07

CAS簡介

CAS的全稱為compare and swap簡單的解釋為比較交換,這個過程其實是發生在記憶體中的,應該說是組合語言的一個操作過程。

AtomicInteger

incrementAndGet()方法,將當前值加1並返回。

// AtomicInteger.java
public final int incrementAndGet() {
    // getAndAddInt返回的是舊值並不是更新後的值,所以這裡返回的是舊值加1
    return unsafe.getAndAddInt(this, valueOffset, 1) + 1; 
}

valueoffset是AtomicInteger中被volatile關鍵字修飾的value在記憶體中的偏移量,類中的定義如下。

// AtomicInteger.java
// 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; // 使用volatile修飾,保證獲取的都是最新值

可以看出這個偏移量在類載入過程中就得到了

// Unsafe.java
/**
 * var1:物件的引用
 * var2:值的偏移量
 * var4:增量
 */
public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        // 這是一個native方法,拿著物件的引用以及位偏移量從記憶體中拿到值
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));// 如果更新失敗,自旋嘗試直到成功

    return var5; // 這裡返回的還是舊值
}

// 這是一個native方法
 // 如果 var1 物件中 記憶體偏移量為 var2 的 value 變數的值為 var4,則更新該值為 var5
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

compareAndSwapInt傳入了四個引數:

var1:物件的引用

var2:值的偏移量

var5:期望值

var5+var4:更新值

它是一個native方法,如果更新值代替舊值成功則返回true,反則返回false

本作品採用《CC 協議》,轉載必須註明作者和本文連結