• AtomicReference 源码分析


    AtomicReference

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

    1)AtomicReference 可以原子更新引用对象。
    2)compareAndSet 操作是一条 CPU 指令,不会发生上下文切换,执行效率高。
    使用锁保证对象同步时,会触发一次系统调用和上下文切换,执行效率低。
    

    如何使用 AtomicReference?

    1)多线程环境下需要并发修改对象的多个属性时,使用 AtomicReference【
    读取、修改、更新需要在同一个循环中,并根据 compareAndSet 的结果来判断是否要继续自旋】。
    

    使用 AtomicReference 有什么风险?

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

    AtomicReference 核心操作的实现原理?

    创建实例

        private static final VarHandle VALUE;
        static {
            try {
                final MethodHandles.Lookup l = MethodHandles.lookup();
                VALUE = l.findVarHandle(AtomicReference.class, "value", Object.class);
            } catch (final ReflectiveOperationException e) {
                throw new Error(e);
            }
        }
    
        /**
         * volatile 引用值
         */
        private volatile V value;
    
        /**
         * 基于初始对象 initialValue 创建一个 AtomicReference 实例
         */
        public AtomicReference(V initialValue) {
            value = initialValue;
        }
    
        /**
         * 创建一个关联对象为 null 的 AtomicReference 实例
         */
        public AtomicReference() {
        }
    

    尝试原子更新

        /**
         *  原子的将引用值设置为 newValue,如果旧值 == expectedValue,设置成功返回 true,否则返回 false。
         *
         * @param expectedValue 期望值
         * @param newValue  新值
         */
        public final boolean compareAndSet(V expectedValue, V newValue) {
            return AtomicReference.VALUE.compareAndSet(this, expectedValue, newValue);
        }
    

    读取当前值

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

    原子地将旧值更新为 newValue,并返回旧值

        /**
         * 原子地将旧值更新为 newValue,并返回旧值
         * with memory effects as specified by {@link VarHandle#getAndSet}.
         */
        @SuppressWarnings("unchecked")
        public final V getAndSet(V newValue) {
            return (V)AtomicReference.VALUE.getAndSet(this, newValue);
        }
    

    使用函数式接口 updateFunction 基于旧值计算新值,并将旧值替换为计算值,返回旧值

        /**
         * 使用函数式接口 updateFunction 基于旧值计算新值,并将旧值替换为计算值,返回旧值
         */
        public final V getAndUpdate(UnaryOperator<V> updateFunction) {
            V prev = get(), next = null;
            for (boolean haveNext = false;;) {
                if (!haveNext) {
                    next = updateFunction.apply(prev);
                }
                if (weakCompareAndSetVolatile(prev, next)) {
                    return prev;
                }
                haveNext = prev == (prev = get());
            }
        }
    
        /**
         * 如果当前值==expectedValue,则尝试原子地将其更新为 newValue,更新成功返回 true
         * with memory effects as specified by
         * {@link VarHandle#weakCompareAndSet}.
         */
        public final boolean weakCompareAndSetVolatile(V expectedValue, V newValue) {
            return AtomicReference.VALUE.weakCompareAndSet(this, expectedValue, newValue);
        }
    

    使用函数式接口 updateFunction 基于旧值计算新值,并将旧值替换为计算值,返回新值

        /**
         * 使用函数式接口 updateFunction 基于旧值计算新值,并将旧值替换为计算值,返回新值
         */
        public final V updateAndGet(UnaryOperator<V> updateFunction) {
            V prev = get(), next = null;
            for (boolean haveNext = false;;) {
                if (!haveNext) {
                    next = updateFunction.apply(prev);
                }
                if (weakCompareAndSetVolatile(prev, next)) {
                    return next;
                }
                haveNext = prev == (prev = get());
            }
        }
    

    使用函数式接口 accumulatorFunction 基于旧值和形参 x 计算新值,并将旧值替换为计算值,返回旧值

        /**
         *  使用函数式接口 accumulatorFunction 基于旧值和形参 x 计算新值,并将旧值替换为计算值,返回旧值
         */
        public final V getAndAccumulate(V x,
                BinaryOperator<V> accumulatorFunction) {
            V prev = get(), next = null;
            for (boolean haveNext = false;;) {
                if (!haveNext) {
                    next = accumulatorFunction.apply(prev, x);
                }
                if (weakCompareAndSetVolatile(prev, next)) {
                    return prev;
                }
                haveNext = prev == (prev = get());
            }
        }
    

    使用函数式接口 accumulatorFunction 基于旧值和形参 x 计算新值,并将旧值替换为计算值,返回新值

        /**
         *  使用函数式接口 accumulatorFunction 基于旧值和形参 x 计算新值,并将旧值替换为计算值,返回新值
         */
        public final V accumulateAndGet(V x,
                BinaryOperator<V> accumulatorFunction) {
            V prev = get(), next = null;
            for (boolean haveNext = false;;) {
                if (!haveNext) {
                    next = accumulatorFunction.apply(prev, x);
                }
                if (weakCompareAndSetVolatile(prev, next)) {
                    return next;
                }
                haveNext = prev == (prev = get());
            }
        }
    
  • 相关阅读:
    【CF446D】DZY Loves Games 高斯消元+矩阵乘法
    【CF542D】Superhero's Job 暴力
    【CF660E】Different Subsets For All Tuples 结论题
    【CF666C】Codeword 结论题+暴力
    【CF666E】Forensic Examination 广义后缀自动机+倍增+线段树合并
    【CF461E】Appleman and a Game 倍增floyd
    【CF471E】MUH and Lots and Lots of Segments 扫描线+并查集+线段树+set
    【CF480D】Parcels DP
    【CF497E】Subsequences Return 矩阵乘法
    SSAS 项目部署失败的问题
  • 原文地址:https://www.cnblogs.com/zhuxudong/p/10055017.html
Copyright © 2020-2023  润新知