zoukankan      html  css  js  c++  java
  • CAS / ABA

    CAS / ABA

    标签(空格分隔): 操作系统


    1. CAS 解决 Volatile 不保证原子性的问题

    /**
     * Atomically increments by one the current value.
     *
     * @return the previous value
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
    
    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
    
        return var5;
    }
    

    Volatile不保证原子性的解决方案, 在其中我们可以看到我们通过atomicInteger.getAndIncrement(), 获取值并且将其+1, 重点在于this.compareAndSwapInt(var1, var2, var5, var5 + var4) 通过乐观锁的方法, 相当于实现了原子性的操作.

    2. CAS 导致的 ABA 问题解决

    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicReference;
    import java.util.concurrent.atomic.AtomicStampedReference;
    
    /**
     * CAS会导致ABA问题:
     *     CAS算法实现一个重要前提需要取出内存中某时刻的数据并且在当下时刻进行比较并替换(Compare And Set), 那么在这个时间差的时候可能会导致数据的变化.
     *     比如: 一个线程one从内存位置中V中取出A, 这个时候另一个线程two也从内存中取出A. 此时线程one和two都持有位置V中A的备份, 在这个时候two将A->B->A 并写入主存当中.
     *     线程one去进行CAS操作的时候, 发现内存中仍然是A, 然后线程one操作成功.
     *
     *   这个问题主要看线程two对中间操作对 线程one有影响没, 如果有影响的话. 需要解决一下CAS问题.
     */
    public class Test {
    
        private static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);
        private static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 1);
    
        public static void main(String[] args) {
            /*         ABA问题产生实例 Start */
            new Thread(()->{
                atomicReference.compareAndSet(100,101);
                atomicReference.compareAndSet(101,100);
            },"t1").start();
    
            new Thread(()->{
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(atomicReference.compareAndSet(100, 2019)+"	"+atomicReference.get());
            }).start();
            /* ABA问题产生实例 End */
    
    
    
            /* ABA问题解决实例 Start */
            new Thread(() -> {
                int stamp = atomicStampedReference.getStamp();
                System.out.println(Thread.currentThread().getName() + "	  第一次版本号 : " + atomicStampedReference.getStamp());
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                atomicStampedReference.compareAndSet(100, 101, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
                System.out.println(Thread.currentThread().getName() + "	  第二次版本号 : " + atomicStampedReference.getStamp());
                atomicStampedReference.compareAndSet(101, 100, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
                System.out.println(Thread.currentThread().getName() + "	  第三次版本号 : " + atomicStampedReference.getStamp());
            }, "t3").start();
    
            new Thread(() -> {
                int stamp = atomicStampedReference.getStamp();
                System.out.println(Thread.currentThread().getName() + "	  第一次版本号 : " + atomicStampedReference.getStamp());
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("是否修改成功: " + atomicStampedReference.compareAndSet(100, 2019, 1, atomicStampedReference.getStamp() + 1) + "	 当前的stamp值: " + atomicStampedReference.getStamp());
                System.out.println("当前最新值: " + atomicStampedReference.getReference());
            }, "t4").start();
            /* ABA问题 解决实例 End */
    
        }
    }
    
    
  • 相关阅读:
    地址级联选择器(element-china-area-data插件)
    el-table在每一行拿到对应的index(scope.$index)
    el-table中的label换行问题(重点white-space)
    调用outlook来发送邮件
    利用apifox来测试API
    注解@ConfigurationProperties使用方法
    异步加载js,兼容IE
    Exceptionless安装的一些坑
    MVC 源码系列之控制器执行(二)
    MVC 源码系列之控制器执行(一)
  • 原文地址:https://www.cnblogs.com/A-FM/p/11655743.html
Copyright © 2011-2022 走看看