AtomicInteger 源码分析

AtomicInteger

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

支持原子更新的 int 值。

如何使用 AtomicInteger?

1)需要被多线程并发访问的原子计数器。
2)使用 AtomicInteger.compareAndSet 实现非阻塞的线程安全工具类。

使用 AtomicInteger 有什么风险?

1)高并发场景下,自旋 CAS 长时间失败会导致 CPU 飙升,推荐使用 LongAdder。

AtomicInteger 核心操作的实现原理?

创建实例

    /**
     * 可原子更新的 int 值
     */
    private volatile int value;

    /**
     * 创建初始值为 initialValue 的新 AtomicInteger 实例
     */
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }

    /**
     * 创建初始值为 0 的新 AtomicInteger 实例
     */
    public AtomicInteger() {
    }

尝试以原子的方式更新值

    /**
     * 如果当前值 == 预期值,则以原子方式将当前值设置为给定的更新值
     * with memory effects as specified by {@link VarHandle#compareAndSet}.
     */
    public final boolean compareAndSet(int expectedValue, int newValue) {
        return U.compareAndSetInt(this, AtomicInteger.VALUE, expectedValue, newValue);
    }

读取值

    /**
     * 读取值
     * with memory effects as specified by {@link VarHandle#getVolatile}.
     */
    public final int get() {
        return value;
    }

以原子方式将当前值加 1,并返回旧值

    /**
     * 以原子方式将当前值加 1,并返回旧值。
     * with memory effects as specified by {@link VarHandle#getAndAdd}.
     */
    public final int getAndIncrement() {
        return U.getAndAddInt(this, AtomicInteger.VALUE, 1);
    }

Unsafe#
    /**
     * 1)原子地将给定的值累加到当前值、或指定索引为 offset 的数组元素上。
     */
    @HotSpotIntrinsicCandidate
    public int getAndAddInt(Object o, long offset, int delta) {
        int v;
        do {
            // 以 volatile 的方式读取值
            v = getIntVolatile(o, offset);
        } while (!weakCompareAndSetInt(o, offset, v, v + delta));
        // 返回旧值
        return v;
    }

    @HotSpotIntrinsicCandidate
    public boolean weakCompareAndSetInt(Object o, long offset,
            int expected,
            int x) {
        return compareAndSetInt(o, offset, expected, x);
    }

    /**
     * 如果当前值是 expected,则将目标值更新为 x,该操作具有 volatile 读和写内存语义。
     * <p>This operation has memory semantics of a {@code volatile} read
     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
     */
    @HotSpotIntrinsicCandidate
    public native boolean compareAndSetInt(Object o, long offset,
            int expected,
            int x);

以原子方式写入新值,并返回旧值

    /**
     * 以原子方式写入新值,并返回旧值
     * with memory effects as specified by {@link VarHandle#getAndSet}.
     */
    public final int getAndSet(int newValue) {
        return U.getAndSetInt(this, AtomicInteger.VALUE, newValue);
    }

以原子方式将当前值减 1,并返回旧值

    /**
     * 以原子方式将当前值减 1,并返回旧值
     * with memory effects as specified by {@link VarHandle#getAndAdd}.
     */
    public final int getAndDecrement() {
        return U.getAndAddInt(this, AtomicInteger.VALUE, -1);
    }

以原子方式将给定值与当前值相加,并返回旧值

    /**
     * 以原子方式将给定值与当前值相加,并返回旧值
     * with memory effects as specified by {@link VarHandle#getAndAdd}.
     */
    public final int getAndAdd(int delta) {
        return U.getAndAddInt(this, AtomicInteger.VALUE, delta);
    }

原子更新当前值为函数式接口 updateFunction 的计算值,并返回旧值

    /**
     * 原子更新当前值为函数式接口 updateFunction 的计算值,并返回旧值。
     */
    public final int getAndUpdate(IntUnaryOperator updateFunction) {
        // 读取旧值
        int prev = get(), next = 0;
        for (boolean haveNext = false;;) {
            if (!haveNext) {
                // 计算新值
                next = updateFunction.applyAsInt(prev);
            }
            // 原子更新值,如果成功则返回旧值
            if (weakCompareAndSetVolatile(prev, next)) {
                return prev;
            }
            // 更新失败则重新读取旧值,如果出现 ABA 问题,则不会重新计算
            haveNext = prev == (prev = get());
        }
    }

原子更新当前值为函数式接口 accumulatorFunction 的计算值,并返回旧值

    /**
     * 原子更新当前值为函数式接口 accumulatorFunction 的计算值,并返回旧值
     */
    public final int getAndAccumulate(int x,
            IntBinaryOperator accumulatorFunction) {
        // 读取旧值
        int prev = get(), next = 0;
        for (boolean haveNext = false;;) {
            if (!haveNext) {
                // 基于旧值和 x 计算新值
                next = accumulatorFunction.applyAsInt(prev, x);
            }
            // 原子更新旧值
            if (weakCompareAndSetVolatile(prev, next)) {
                return prev;
            }
            haveNext = prev == (prev = get());
        }
    }

以原子方式将当前值加 1,并返回新值

    /**
     * 以原子方式将当前值加 1,并返回新值
     * with memory effects as specified by {@link VarHandle#getAndAdd}.
     */
    public final int incrementAndGet() {
        return U.getAndAddInt(this, AtomicInteger.VALUE, 1) + 1;
    }

以原子方式将当前值减 1,并返回新值

    /**
     * 以原子方式将当前值减 1,并返回新值
     * with memory effects as specified by {@link VarHandle#getAndAdd}.
     */
    public final int decrementAndGet() {
        return U.getAndAddInt(this, AtomicInteger.VALUE, -1) - 1;
    }

以原子方式将给定值与当前值相加,并返回新值

    /**
     * 以原子方式将给定值与当前值相加,并返回新值
     * with memory effects as specified by {@link VarHandle#getAndAdd}.
     */
    public final int addAndGet(int delta) {
        return U.getAndAddInt(this, AtomicInteger.VALUE, delta) + delta;
    }

以原子方式更新值【新值通过函数式接口计算得到,参数为旧值】,并返回新值

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

以原子方式更新值【新值通过函数式接口计算得到,参数为旧值和参考更新值】,并返回新值

    /**
     *  以原子方式更新值【新值通过函数式接口计算得到,参数为旧值和参考更新值】,并返回新值
     */
    public final int accumulateAndGet(int x,
            IntBinaryOperator accumulatorFunction) {
        int prev = get(), next = 0;
        for (boolean haveNext = false;;) {
            if (!haveNext) {
                next = accumulatorFunction.applyAsInt(prev, x);
            }
            if (weakCompareAndSetVolatile(prev, next)) {
                return next;
            }
            haveNext = prev == (prev = get());
        }
    }
原文地址:https://www.cnblogs.com/zhuxudong/p/10053617.html