zoukankan      html  css  js  c++  java
  • AtomicStampedReference 源码分析

    AtomicStampedReference

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

    1)AtomicStampedReference 维护带有整数标识的对象引用,可以用原子方式对其进行更新。
    2)AtomicStampedReference 能够解决 CAS 的 ABA 问题。
    

    如何使用 AtomicStampedReference?

    1)使用 AtomicStampedReference 解决无锁 CAS 过程中的 ABA 问题,特别是涉及资金时。
    

    使用 AtomicStampedReference 有什么风险?

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

    AtomicStampedReference 核心操作的实现原理?

    创建实例

        private static class Pair<T> {
            /**
             * 目标对象引用
             */
            final T reference;
            /**
             * 整形标记
             */
            final int stamp;
            private Pair(T reference, int stamp) {
                this.reference = reference;
                this.stamp = stamp;
            }
            static <T> Pair<T> of(T reference, int stamp) {
                return new Pair<>(reference, stamp);
            }
        }
    
        private volatile Pair<V> pair;
    
        /**
         * 创建具有给定对象引用和标识值的新 AtomicStampedReference 实例
         */
        public AtomicStampedReference(V initialRef, int initialStamp) {
            pair = Pair.of(initialRef, initialStamp);
        }
    

    尝试原子更新

        /**
         * 如果旧引用==expectedReference && 旧整形标记==expectedStamp,
         * 则尝试原子更新引用为 newReference,时间标记为 newStamp
         */
        public boolean compareAndSet(V   expectedReference,
                V   newReference,
                int expectedStamp,
                int newStamp) {
            final Pair<V> current = pair;
            return
                    expectedReference == current.reference &&
                    expectedStamp == current.stamp &&
                    (newReference == current.reference &&
                    newStamp == current.stamp ||
                    casPair(current, Pair.of(newReference, newStamp)));
        }
    

    读取值

        /**
         *  读取引用值
         */
        public V getReference() {
            return pair.reference;
        }
    
        /**
         *  读取整形标记
         */
        public int getStamp() {
            return pair.stamp;
        }
    
        /**
         *  读取引用值,并将整形标记存储到形参数组索引为 0 的位置
         */
        public V get(int[] stampHolder) {
            final Pair<V> pair = this.pair;
            stampHolder[0] = pair.stamp;
            return pair.reference;
        }
    

    写入值

        /**
         * 无条件地更新引用值和时间标记
         */
        public void set(V newReference, int newStamp) {
            final Pair<V> current = pair;
            if (newReference != current.reference || newStamp != current.stamp) {
                this.pair = Pair.of(newReference, newStamp);
            }
        }
    

    原子更新值,并发更新时可能失败

        /**
         * 如果旧引用==expectedReference && 旧整形标记==expectedStamp,
         * 则尝试原子更新引用为 newReference,时间标记为 newStamp
         */
        public boolean weakCompareAndSet(V   expectedReference,
                V   newReference,
                int expectedStamp,
                int newStamp) {
            return compareAndSet(expectedReference, newReference,
                    expectedStamp, newStamp);
        }
    
        /**
         * 如果旧引用==expectedReference && 旧整形标记==expectedStamp,
         * 则尝试原子更新引用为 newReference,时间标记为 newStamp
         */
        public boolean compareAndSet(V   expectedReference,
                V   newReference,
                int expectedStamp,
                int newStamp) {
            final Pair<V> current = pair;
            return
                    expectedReference == current.reference &&
                    expectedStamp == current.stamp &&
                    (newReference == current.reference &&
                    newStamp == current.stamp ||
                    casPair(current, Pair.of(newReference, newStamp)));
        }
    
        private static final VarHandle PAIR;
        static {
            try {
                final MethodHandles.Lookup l = MethodHandles.lookup();
                PAIR = l.findVarHandle(AtomicStampedReference.class, "pair",
                        Pair.class);
            } catch (final ReflectiveOperationException e) {
                throw new Error(e);
            }
        }
    
        private boolean casPair(Pair<V> cmp, Pair<V> val) {
            return AtomicStampedReference.PAIR.compareAndSet(this, cmp, val);
        }
    
  • 相关阅读:
    第1课 Git、谁与争锋
    程序员最真实的10个瞬间
    程序员最真实的10个瞬间
    一文读懂前端缓存
    一文读懂前端缓存
    一文读懂前端缓存
    EF使用CodeFirst创建数据库和表
    EF使用CodeFirst创建数据库和表
    EF使用CodeFirst创建数据库和表
    ASP.NET MVC的过滤器笔记
  • 原文地址:https://www.cnblogs.com/zhuxudong/p/10055081.html
Copyright © 2011-2022 走看看