• 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());
            }
        }
    
  • 相关阅读:
    价值投资-买股票操作流程
    win10安装mysql8
    .NET Debugging Demos Lab 7: Memory Leak
    .NET Debugging Demos Lab 6: Debugging Challenge
    .NET Debugging Demos Lab 5: Crash
    .NET Debugging Demos Lab 3: Memory
    .NET Debugging Demos Lab 1: Hang- Walkthrough
    .NET Debugging Demos Lab 1: Hang
    【翻译 windbg-3】高级WinDbg 使用教程
    【翻译 windbg-2】Getting started with windbg
  • 原文地址:https://www.cnblogs.com/zhuxudong/p/10055017.html
Copyright © 2020-2023  润新知