• 《Java并发编程实战》笔记-OneValueCache与原子引用技术


    /**
     * NumberRange
     * <p/>
     * Number range class that does not sufficiently protect its invariants
     *
     * @author Brian Goetz and Tim Peierls
     */
    
    public class NumberRange {
        // INVARIANT: lower <= upper
        private final AtomicInteger lower = new AtomicInteger(0);
        private final AtomicInteger upper = new AtomicInteger(0);
    
        public void setLower(int i) {
            // Warning -- unsafe check-then-act
            if (i > upper.get())
                throw new IllegalArgumentException("can't set lower to " + i + " > upper");
            lower.set(i);
        }
    
        public void setUpper(int i) {
            // Warning -- unsafe check-then-act
            if (i < lower.get())
                throw new IllegalArgumentException("can't set upper to " + i + " < lower");
            upper.set(i);
        }
    
        public boolean isInRange(int i) {
            return (i >= lower.get() && i <= upper.get());
        }
    }

    NumberRange既不能使用指向不可变对象的volatile引用来安全地实现上界和下界,也不能使用原子的整数来保存这两个边界。由于有一个不变性条件限制了两个数值,并且它们无法在同时更新时还维持该不变性条件,因此如果在数值范围类中使用volatile引用或者多个原子整数,那么将出现不安全的“先检查再运行”操作序列。

    可以将OneValueCache中的技术与原子引用结合起来,它在更新上界或下界时能避免NumberRange的竞态条件。

    /**
     * CasNumberRange
     * <p/>
     * Preserving multivariable invariants using CAS
     *
     * @author Brian Goetz and Tim Peierls
     */
    @ThreadSafe
    public class CasNumberRange {
        @Immutable
        private static class IntPair {
            // INVARIANT: lower <= upper
            final int lower;
            final int upper;
    
            public IntPair(int lower, int upper) {
                this.lower = lower;
                this.upper = upper;
            }
        }
    
        private final AtomicReference<IntPair> values = new AtomicReference<IntPair>(new IntPair(0, 0));
    
        public int getLower() {
            return values.get().lower;
        }
    
        public int getUpper() {
            return values.get().upper;
        }
    
        public void setLower(int i) {
            while (true) {
                IntPair oldv = values.get();
                if (i > oldv.upper)
                    throw new IllegalArgumentException("Can't set lower to " + i + " > upper");
                IntPair newv = new IntPair(i, oldv.upper);
                if (values.compareAndSet(oldv, newv))
                    return;
            }
        }
    
        public void setUpper(int i) {
            while (true) {
                IntPair oldv = values.get();
                if (i < oldv.lower)
                    throw new IllegalArgumentException("Can't set upper to " + i + " < lower");
                IntPair newv = new IntPair(oldv.lower, i);
                if (values.compareAndSet(oldv, newv))
                    return;
            }
        }
    }
  • 相关阅读:
    2015年中国500强企业
    汇编语言
    oracle数据库学习路线
    OI生涯回忆录
    NOIP 2020游记
    CF223B Two Strings 题解
    CSP-S 2020游记
    CSP/NOIP 注意事项(2020)
    Luogu P6583 回首过去 题解
    Luogu P2210 Haywire 题解
  • 原文地址:https://www.cnblogs.com/birdstudio/p/6610132.html
Copyright © 2020-2023  润新知