JDK源码分析之CAS

作者: 一岁一枯荣啊 | 来源:发表于2019-10-17 23:06 被阅读0次

    一,什么是CAS?

    (Conmpare And Swap)对比并替换。它将内存的内容与对比值进行校验,相同则替换,否则返回false.

    两步操作,但是由于底层硬件的支持,两步操作能一步完成,避免独占锁资源浪费,保证了原子性

    /Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home/jre/lib/rt.jar!/java/util/concurrent/atomic

    二、JAVA中CAS是怎么是实现的

    JAVA中的CAS操作都是通过sun包下Unsafe类实现的,而Unsafe类中的方法都是native方法,由JVM本地实现

     */
        public final void lazySet(int newValue) {
            unsafe.putOrderedInt(this, valueOffset, newValue);
        }
    
        /**
         * Atomically sets to the given value and returns the old value.
         *
         * @param newValue the new value
         * @return the previous value
         */
        public final int getAndSet(int newValue) {
            return unsafe.getAndSetInt(this, valueOffset, newValue);
        }
    
        /**
         * Atomically sets the value to the given updated value
         * if the current value {@code ==} the expected value.
         *
         * @param expect the expected value
         * @param update the new value
         * @return {@code true} if successful. False return indicates that
         * the actual value was not equal to the expected value.
         */
        public final boolean compareAndSet(int expect, int update) {
            return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
        }
    
        /**
         * Atomically sets the value to the given updated value
         * if the current value {@code ==} the expected value.
         *
         * <p><a href="package-summary.html#weakCompareAndSet">May fail
         * spuriously and does not provide ordering guarantees</a>, so is
         * only rarely an appropriate alternative to {@code compareAndSet}.
         *
         * @param expect the expected value
         * @param update the new value
         * @return {@code true} if successful
         */
        public final boolean weakCompareAndSet(int expect, int update) {
            return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
        }
    
        /**
         * Atomically increments by one the current value.
         *
         * @return the previous value
         */
        public final int getAndIncrement() {
            return unsafe.getAndAddInt(this, valueOffset, 1);
        }
    
        /**
         * Atomically decrements by one the current value.
         *
         * @return the previous value
         */
        public final int getAndDecrement() {
            return unsafe.getAndAddInt(this, valueOffset, -1);
        }
    
        /**
         * Atomically adds the given value to the current value.
         *
         * @param delta the value to add
         * @return the previous value
         */
        public final int getAndAdd(int delta) {
            return unsafe.getAndAddInt(this, valueOffset, delta);
        }
    
        /**
         * Atomically increments by one the current value.
         *
         * @return the updated value
         */
        public final int incrementAndGet() {
            return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
        }
    
        /**
         * Atomically decrements by one the current value.
         *
         * @return the updated value
         */
        public final int decrementAndGet() {
            return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
        }
    
    
    

    三、ABA问题

    比如内存中一数据 str="A";

    第一步: 线程1取出str 的值"A",准备执行变更为"D",还未执行
    第二步: 线程2取出str 的值"A" ,执行cas("A","B") ,把值变成了"B"
    第三步: 线程3取出str 的值"B" ,执行cas("B","A") ,把值变成了"A"
    第四步: 线程1继续执行cas("A","D")

    这个过程就是有ABA问题存在的。因为在线程一执行的中间,数据已经被其他线程修改从而发生了变化,虽然恢复了原值,但是线程1没有感知到,以为没有发生过变化,这是不能被忽略的。

    解决方式:JAV提供了时间戳的CAS。AtomicStampedReference

    三、哪里用到了CAS

    • AbstractQueuedSynchronizer
    • ThreadPoolExecuter addWorker方法

    相关文章

      网友评论

        本文标题:JDK源码分析之CAS

        本文链接:https://www.haomeiwen.com/subject/uujbmctx.html