Java - AtomicIntegerArray 源码阅读笔记

in TCEH Java

简介

  顾名思义,并发情况下能确保数据准确性的整型数组。并提供了对数组元素的自增自减等操作。

AtomicIntegerArray 类

public class AtomicIntegerArray implements java.io.Serializable {
    private static final long serialVersionUID = 2862133569453604235L;

    private static final Unsafe unsafe = Unsafe.getUnsafe();
    // 获取整型数组起始偏移量
    private static final int base = unsafe.arrayBaseOffset(int[].class);
    // 为了使用二进制提高性能,这里单个偏移量用2ⁿ来表示,n就等于shift
    private static final int shift;
    private final int[] array;

    static {
        // 单个元素的偏移量
        int scale = unsafe.arrayIndexScale(int[].class);
        // 偏移量不是2的倍数,则抛异常
        if ((scale & (scale - 1)) != 0)
            throw new Error("data type scale not a power of two");
        // 计算scale有几个零
        shift = 31 - Integer.numberOfLeadingZeros(scale);
    }
    ...
}

构造方法

   public AtomicIntegerArray(int length) {
        array = new int[length];
    }    
    public AtomicIntegerArray(int[] array) {
        this.array = array.clone();
    }

getAndAdd() 方法

    public final int getAndAdd(int i, int delta) {
        // 设置i位置的值为旧值+delta,并返回旧值
        return unsafe.getAndAddInt(array, checkedByteOffset(i), delta);
    }

checkedByteOffset() 方法

检查索引是否越界及返回索引偏移量

    private long checkedByteOffset(int i) {
        if (i < 0 || i >= array.length)
            throw new IndexOutOfBoundsException("index " + i);

        return byteOffset(i);
    }

byteOffset() 方法

获取指定下标的偏移量

    private static long byteOffset(int i) {
        // i左移shift位,其实就是 i*(2的shift次方)+数组起始偏移量,就是索引的偏移量
        return ((long) i << shift) + base;
    }

addAndGet() 方法

    public final int addAndGet(int i, int delta) {
        // // 设置i位置的值为旧值+delta,返回旧值+delta
        return getAndAdd(i, delta) + delta;
    }

get() 方法

    public final int get(int i) {
        return getRaw(checkedByteOffset(i));
    }

getRaw() 方法

    private int getRaw(long offset) {
        // 返回指定偏移量的值
        return unsafe.getIntVolatile(array, offset);
    }

getRaw() 方法

jdk1.8 提供的方法

    public final int getAndUpdate(int i, IntUnaryOperator updateFunction) {
        long offset = checkedByteOffset(i);
        int prev, next;
        do {
            // 旧值
            prev = getRaw(offset);           
            // 通过自定义实现IntUnaryOperator接口的applyAsInt,返回新值
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSetRaw(offset, prev, next));// 替换为新值
        return prev;// 返回旧值
    }