J.U.C之Atomic:数组类型的原子类

数组类型的原子类

类名 说明
AtomicIntegerArray 原子更新整型数组里的元素。
AtomicLongArray 原子更新长整型数组里的元素。
AtomicReferenceArray 原子更新引用类型数组的元素。
AtomicBooleanArray 原子更新布尔类型数组的元素。

AtomicIntegerArray

AtomicIntegerArray 主要时用来封装对数组中某个元素操作。

原理解析

AtomicIntegerArray 对数组元素的操作使用Unsafe类两个重要的方法

  • arrayBaseOffset:获取该类型的数组,在对象存储时,存放第一个元素的内存地址
  • arrayIndexScale: 返回数组中每一个元素占用的大小

当我知道了起始位置,每一个元素的大小就可以推算出数组中每个元素对应偏移位置。那么只需要使用unsafe对数组对象操作方法设置值。

private static final Unsafe unsafe = Unsafe.getUnsafe();
    /** 获取该类型的数组,在对象存储时,存放第一个元素的内存地址 **/
    private static final int base = unsafe.arrayBaseOffset(int[].class);
    /** 用于计算数组中每个元素的偏移位置 **/
    private static final int shift;
    /** 操作对象 **/
    private final int[] array;

    static {
        /** 返回数组中每一个元素占用的大小(int类型返回4)**/
        int scale = unsafe.arrayIndexScale(int[].class);
        if ((scale & (scale - 1)) != 0)
            throw new Error("data type scale not a power of two");
        /** 返回 scale 高位连续0的个数(int 类型返回2) **/
        shift = 31 - Integer.numberOfLeadingZeros(scale);
    }

    /**
     * 获取数组中每个元素的偏移位置(存在校验)
     */
    private long checkedByteOffset(int i) {
        if (i < 0 || i >= array.length)
            throw new IndexOutOfBoundsException("index " + i);

        return byteOffset(i);
    }

    /**
     * 获取数组中每个元素的偏移位置
     */
    private static long byteOffset(int i) {
        return ((long) i << shift) + base;
    }

对数组元素的操作

/**
    * 使用CAS将位置{@code i}的元素设置为给定值newValue,成功返回true,失败返回false
     */
    public final boolean compareAndSet(int i, int expect, int update) {
        return compareAndSetRaw(checkedByteOffset(i), expect, update);
    }

    private boolean compareAndSetRaw(long offset, int expect, int update) {
        return unsafe.compareAndSwapInt(array, offset, expect, update);
    }

源码解析

构造方法

/**
     * 实例化一个AtomicIntegerArray,设置素组大小
     */
    public AtomicIntegerArray(int length) {
        array = new int[length];
    }

    /**
     * 创建一个新的AtomicIntegerArray,并给定一个数组初始化
     */
    public AtomicIntegerArray(int[] array) {
        // Visibility guaranteed by final field guarantees
        this.array = array.clone();
    }

原子操作

/**
     * 获取位置{@code i}的当前值。
     */
    public final int get(int i) {
        return getRaw(checkedByteOffset(i));
    }

    private int getRaw(long offset) {
        return unsafe.getIntVolatile(array, offset);
    }

    /**
     * 将位置{@code i}的元素设置为给定值。
     */
    public final void set(int i, int newValue) {
        unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);
    }

    /**
       将位置{@code i}的元素设置为给定值newValue(不保证其他线程立刻看到),
          因为value设置为volatile一般情况下其他线程都可见,这里就是抛弃了volatile特性,
          1 清空其他线程中缓存,保证可见性
          2 内存屏障保证有序性。
     *
     */
    public final void lazySet(int i, int newValue) {
        unsafe.putOrderedInt(array, checkedByteOffset(i), newValue);
    }

    /**
     * 原子方式将位置{@code i}的元素设置为给定值newValue并返回旧值。(内部使用CAS乐观锁+循环)
     */
    public final int getAndSet(int i, int newValue) {
        return unsafe.getAndSetInt(array, checkedByteOffset(i), newValue);
    }

    /**
     * 使用CAS将位置{@code i}的元素设置为给定值newValue,成功返回true,失败返回false
     */
    public final boolean compareAndSet(int i, int expect, int update) {
        return compareAndSetRaw(checkedByteOffset(i), expect, update);
    }

    private boolean compareAndSetRaw(long offset, int expect, int update) {
        return unsafe.compareAndSwapInt(array, offset, expect, update);
    }

    /**
     * 使用CAS将位置{@code i}的元素设置为给定值newValue,成功返回true,失败返回false
     */
    public final boolean weakCompareAndSet(int i, int expect, int update) {
        return compareAndSet(i, expect, update);
    }

    /**
     * 以原子方式将位置{@code i}的元素+1。(内部使用CAS乐观锁+循环),返回旧值
     */
    public final int getAndIncrement(int i) {
        return getAndAdd(i, 1);
    }

    /**
     * 以原子方式将位置{@code i}的元素-1。(内部使用CAS乐观锁+循环),返回旧值
     */
    public final int getAndDecrement(int i) {
        return getAndAdd(i, -1);
    }

    /**
     * 以原子方式将位置{@code i}的元素+delta。这里传入负数就是减少|delta|(内部使用CAS乐观锁+循环),返回旧值
     */
    public final int getAndAdd(int i, int delta) {
        return unsafe.getAndAddInt(array, checkedByteOffset(i), delta);
    }

    /**
     * 以原子方式将位置{@code i}的元素+1。(内部使用CAS乐观锁+循环),返回新值
     */
    public final int incrementAndGet(int i) {
        return getAndAdd(i, 1) + 1;
    }

    /**
     * 以原子方式将位置{@code i}的元素-1。(内部使用CAS乐观锁+循环),返回新值
     */
    public final int decrementAndGet(int i) {
        return getAndAdd(i, -1) - 1;
    }

    /**
     * 以原子方式将位置{@code i}的元素+delta。这里传入负数就是减少|delta|(内部使用CAS乐观锁+循环),返回新值
     */
    public final int addAndGet(int i, int delta) {
        return getAndAdd(i, delta) + delta;
    }


    /**
     * 以原子方式将位置{@code i}的元素+执行IntUnaryOperator函数处理,使用CAS乐观锁+循环,返回旧值
     */
    public final int getAndUpdate(int i, IntUnaryOperator updateFunction) {
        long offset = checkedByteOffset(i);
        int prev, next;
        do {
            prev = getRaw(offset);
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSetRaw(offset, prev, next));
        return prev;
    }

    /**
     * 以原子方式将位置{@code i}的元素+执行IntUnaryOperator函数处理,使用CAS乐观锁+循环,返回新值
     */
    public final int updateAndGet(int i, IntUnaryOperator updateFunction) {
        long offset = checkedByteOffset(i);
        int prev, next;
        do {
            prev = getRaw(offset);
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSetRaw(offset, prev, next));
        return next;
    }

    /**
     * 以原子方式将位置{@code i}的元素+执行IntBinaryOperator函数处理,使用CAS乐观锁+循环,返回旧值
     */
    public final int getAndAccumulate(int i, int x,
                                      IntBinaryOperator accumulatorFunction) {
        long offset = checkedByteOffset(i);
        int prev, next;
        do {
            prev = getRaw(offset);
            next = accumulatorFunction.applyAsInt(prev, x);
        } while (!compareAndSetRaw(offset, prev, next));
        return prev;
    }

    /**
     * 以原子方式将位置{@code i}的元素+执行IntBinaryOperator函数处理,使用CAS乐观锁+循环,返回新值
     */
    public final int accumulateAndGet(int i, int x,
                                      IntBinaryOperator accumulatorFunction) {
        long offset = checkedByteOffset(i);
        int prev, next;
        do {
            prev = getRaw(offset);
            next = accumulatorFunction.applyAsInt(prev, x);
        } while (!compareAndSetRaw(offset, prev, next));
        return next;
    }

AtomicLongArray,AtomicReferenceArray,AtomicBooleanArray实现和AtomicIntegerArray实现基本相同就不再详诉。

你可能感兴趣的:(J.U.C之Atomic:数组类型的原子类)