【JUC原始碼】atomic類原始碼淺析

2020-09-22 11:01:01

在 java.util.concurrent.atomic 包中,Atomic 打頭的原子操作類有很多。涉及到 Java 常用的數位型別的,基本都有相應的 Atomic 原子操作類,如下圖所示:
圖片描述
Atomic 打頭的原子操作類,在高並行場景下,都是執行緒安全的,我們可以放心使用。

1.AtomicInteger

主要是呼叫Unsafe類的CAS操作,下面是 AtomicInteger 的部分原始碼:

public class AtomicInteger extends Number implements java.io.Serializable {
    
    // 注:value是被volatile修飾的
    private volatile int value;

    // 初始化
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }
    
    // 得到當前值
    public final int get() {
        return value;
    }
    
    // 自增 1,並返回自增之前的值    
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
    
    // 自減 1,並返回自增之前的值    
    public final int getAndDecrement() {
        return unsafe.getAndAddInt(this, valueOffset, -1);
    }
}

從原始碼中,我們可以看到,執行緒安全的操作方法,底層都是使用 unsafe 方法實現,以上幾個 unsafe 方法不是使用 Java 實現的,都是執行緒安全的。

2.AtomicReference

AtomicInteger 是對 int 型別的值進行自增自減,那如果 Atomic 的物件是個自定義類怎麼辦呢,Java 也提供了自定義物件的原子操作類,叫做 AtomicReference。AtomicReference 類可操作的物件是個泛型,所以支援自定義類,其底層是沒有自增方法的,操作的方法可以作為函數入參傳遞,原始碼如下:

// 對 x 執行 accumulatorFunction 操作
// accumulatorFunction 是個函數,可以自定義想做的事情
// 返回老值
public final V getAndAccumulate(V x,BinaryOperator<V> accumulatorFunction) {
    // prev 是老值,next 是新值
    V prev, next;
    // 自旋 + CAS 保證一定可以替換老值
    do {
        prev = get();
        // 執行自定義操作
        next = accumulatorFunction.apply(prev, x);
    } while (!compareAndSet(prev, next));
    return prev;
}