AtomicIntegerArray 源码分析

AtomicIntegerArray

AtomicIntegerArray 能解决什么问题?什么时候使用 AtomicIntegerArray?

可以用原子方式更新其元素的 int 数组

如何使用 AtomicIntegerArray?

1)多线程环境下需要对整形数组中的单个值执行原子更新时使用 AtomicIntegerArray。

使用 AtomicIntegerArray 有什么风险?

1)高并发场景下,自旋 CAS 长时间失败会导致 CPU 飙升

AtomicIntegerArray 核心操作的实现原理?

创建实例

    private static final VarHandle AA
    = MethodHandles.arrayElementVarHandle(int[].class);
    
    /**
     * 存储 int 值的数组 
     */
    private final int[] array;

    /**
     * 创建给定长度的新 AtomicIntegerArray 实例,所有元素的值都为 0。
     */
    public AtomicIntegerArray(int length) {
        array = new int[length];
    }

读取指定索引处的值

    /**
     * 读取指定索引处的值
     * with memory effects as specified by {@link VarHandle#getVolatile}.
     */
    public final int get(int i) {
        return (int)AtomicIntegerArray.AA.getVolatile(array, i);
    }

以原子方式将索引 i 处的元素值加 1,并返回旧值

    /**
     * 以原子方式将索引 i 处的元素值加 1,并返回旧值
     * with memory effects as specified by {@link VarHandle#getAndAdd}.
     */
    public final int getAndIncrement(int i) {
        return (int)AtomicIntegerArray.AA.getAndAdd(array, i, 1);
    }

以原子方式将索引 i 处的元素值减 1,并返回旧值

    /**
     * 以原子方式将索引 i 处的元素值减 1,并返回旧值
     * with memory effects as specified by {@link VarHandle#getAndAdd}.
     */
    public final int getAndDecrement(int i) {
        return (int)AtomicIntegerArray.AA.getAndAdd(array, i, -1);
    }

以原子方式将索引 i 处的元素值加 delta,并返回旧值

    /**
     * 以原子方式将索引 i 处的元素值加 delta,并返回旧值
     * with memory effects as specified by {@link VarHandle#getAndAdd}.
     */
    public final int getAndAdd(int i, int delta) {
        return (int)AtomicIntegerArray.AA.getAndAdd(array, i, delta);
    }

以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值】计算后的新值,并返回旧值

    /**
     *  以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值】计算后的新值,并返回旧值
     */
    public final int getAndUpdate(int i, IntUnaryOperator updateFunction) {
        int prev = get(i), next = 0;
        for (boolean haveNext = false;;) {
            if (!haveNext) {
                next = updateFunction.applyAsInt(prev);
            }
            if (weakCompareAndSetVolatile(i, prev, next)) {
                return prev;
            }
            haveNext = prev == (prev = get(i));
        }
    }

以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值和参考值】计算后的新值,并返回旧值

    /**
     * 以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值和参考值】计算后的新值,并返回旧值
     */
    public final int getAndAccumulate(int i, int x,
            IntBinaryOperator accumulatorFunction) {
        int prev = get(i), next = 0;
        for (boolean haveNext = false;;) {
            if (!haveNext) {
                next = accumulatorFunction.applyAsInt(prev, x);
            }
            if (weakCompareAndSetVolatile(i, prev, next)) {
                return prev;
            }
            haveNext = prev == (prev = get(i));
        }
    }

以原子方式将索引 i 处的元素值加 1,并返回新值

    /**
     * 以原子方式将索引 i 处的元素值加 1,并返回新值
     * with memory effects as specified by {@link VarHandle#getAndAdd}.
     */
    public final int incrementAndGet(int i) {
        return (int)AtomicIntegerArray.AA.getAndAdd(array, i, 1) + 1;
    }

以原子方式将索引 i 处的元素值减 1,并返回新值

    /**
     * 以原子方式将索引 i 处的元素值减 1,并返回新值
     * with memory effects as specified by {@link VarHandle#getAndAdd}.
     */
    public final int decrementAndGet(int i) {
        return (int)AtomicIntegerArray.AA.getAndAdd(array, i, -1) - 1;
    }

以原子方式将索引 i 处的元素值加 delta,并返回新值

    /**
     * 以原子方式将索引 i 处的元素值加 delta,并返回新值
     * with memory effects as specified by {@link VarHandle#getAndAdd}.
     */
    public final int addAndGet(int i, int delta) {
        return (int)AtomicIntegerArray.AA.getAndAdd(array, i, delta) + delta;
    }

以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值】计算后的新值,并返回新值

    /**
     *  以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值】计算后的新值,并返回新值。
     */
    public final int updateAndGet(int i, IntUnaryOperator updateFunction) {
        int prev = get(i), next = 0;
        for (boolean haveNext = false;;) {
            if (!haveNext) {
                next = updateFunction.applyAsInt(prev);
            }
            if (weakCompareAndSetVolatile(i, prev, next)) {
                return next;
            }
            haveNext = prev == (prev = get(i));
        }
    }

以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值和参考值】计算后的新值,并返回新值

    /**
     *  以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值和参考值】计算后的新值,并返回新值
     */
    public final int accumulateAndGet(int i, int x,
            IntBinaryOperator accumulatorFunction) {
        int prev = get(i), next = 0;
        for (boolean haveNext = false;;) {
            if (!haveNext) {
                next = accumulatorFunction.applyAsInt(prev, x);
            }
            if (weakCompareAndSetVolatile(i, prev, next)) {
                return next;
            }
            haveNext = prev == (prev = get(i));
        }
    }

posted on 2018-12-02 15:55  竺旭东  阅读(388)  评论(0编辑  收藏  举报

导航