ABA问题模拟以及解决方案

【Java并发编程】AtomicReference 原子引用

AtomicReference和AtomicInteger非常类似,不同之处就在于AtomicInteger是对整数的封装,底层采用的是compareAndSwapInt实现CAS,比较的是数值是否相等,而AtomicReference则对应普通的对象引用,底层使用的是compareAndSwapObject实现CAS,比较的是两个对象的地址是否相等。也就是它可以保证你在修改对象引用时的线程安全性。

顺便说一下:引用类型的赋值是原子的。虽然虚拟机规范中说64位操作可以不是原子性的,可以分为两个32位的原子操作,但是目前商用的虚拟机几乎都实现了64位原子操作。

.AtomicReference.set(V newValue) 注意此方法是原子的。这个方法里面就一句代码,引用赋值本身它就是原子性的不会被cpu打断的。

 参考博客: 【Java并发编程】AtomicReference 原子引用

 ABA问题模拟Demo

/**
 * Tips:
 *
 * @author Liuq
 * @version 2019年10月17日
 */
public class ABADemo {

    static AtomicReference   atomicReference=new AtomicReference<>(100);


    public static void main(String [] args){
        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());
        },"t1").start();
    }
}

 ABA问题解决Demo

/**
 * Tips:
 *
 * @author Liuq
 * @version 2019年10月17日
 */
public class ABADemo {

    static AtomicReference atomicReference = new AtomicReference<>(100);
    static AtomicStampedReference atomicStampedReference = new AtomicStampedReference(100, 1);

    public static void main(String[] args) {
     /*   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());
        }, "t2").start();
*/

        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + " 第1次版本号: " + stamp);

            atomicStampedReference.compareAndSet(100, 101,
                    atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
            System.out.println(Thread.currentThread().getName() + " 第2次版本号: " + atomicStampedReference.getStamp());

            atomicStampedReference.compareAndSet(101, 100,
                    atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
            System.out.println(Thread.currentThread().getName() + " 第3次版本号: " + atomicStampedReference.getStamp());

        }, "t3").start();



        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + " 第1次版本号: " + stamp);

            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            boolean b = atomicStampedReference.compareAndSet(100, 2019,
                    stamp, stamp + 1);
            System.out.println(Thread.currentThread().getName() + " 修改是否成功: "+ b+" 当前版本 :" + atomicStampedReference.getStamp());

            System.out.println(Thread.currentThread().getName() + " 当前实际值: " + atomicStampedReference.getReference());

        }, "t4").start();


    }

ABA问题模拟以及解决方案_第1张图片

 多试几次 不是每次都有ABA问题

你可能感兴趣的:(多线程)