zoukankan      html  css  js  c++  java
  • CAS导致的ABA问题及解决:时间戳原子引用AtomicReference、AtomicStampedReference

    1.CAS导致ABA问题:

    CAS算法实现一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并交换,那么在这个时间差中会导致数据的变化。

    比如:线程1从内存位置V中取出A,这时线程2也从V中取出A,线程2进行了一些操作将值改成了B,然后线程2又将V的数据改回A;此时线程1进行CAS操作发现内存中仍然是A,然后线程1操作成功。

    尽管线程1的CAS操作成功,但是不代表这个过程就是没有问题的

    解决ABA问题:利用原子引用+修改版本号(类似时间戳),每次需要获取到版本最新的值进行处理。

    2.原子引用AtomicReference

    ABA问题出现示例:

    package com.mort.test;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicReference;
    
    public class TestAtomicReference {
    
        static AtomicReference<Integer> atomicReference = new AtomicReference<Integer>(100);
        public static void main(String[] args) {
            new Thread(() -> {
                // 执行ABA操作
                atomicReference.compareAndSet(100, 101);
                atomicReference.compareAndSet(101, 100);
            }, "t1").start();
    
            new Thread(()->{
                // 暂停1秒钟t2线程,保证t1完成了一次ABA操作
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(atomicReference.compareAndSet(100, 2019)+"	" + atomicReference.get());
            }, "t2").start();
        }
    }

    3.解决ABA问题:时间戳原子引用AtomicStampedReference

    代码示例:

    package com.mort.test;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicReference;
    import java.util.concurrent.atomic.AtomicStampedReference;
    
    public class TestABASolve {
        //static AtomicReference<Integer> atomicReference = new AtomicReference<Integer>(100);
        static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100,1);
        public static void main(String[] args) {
            new Thread(() -> {
                int stamp = atomicStampedReference.getStamp();
                System.out.println(Thread.currentThread().getName()+"	第1次版本号:"+stamp);
                // 暂停1秒钟t1线程,保证t2拿到版本号与t1相同
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 执行ABA操作
                atomicStampedReference.compareAndSet(100, 101,stamp,stamp+1);
                stamp = atomicStampedReference.getStamp();
                System.out.println(Thread.currentThread().getName()+"	第2次版本号:"+stamp);
                atomicStampedReference.compareAndSet(101, 100, stamp,stamp+1);
    //            System.out.println(Thread.currentThread().getName()+"	第3次版本号:"+atomicStampedReference.getStamp());
            }, "t1").start();
    
            new Thread(()->{
                int stamp = atomicStampedReference.getStamp();
                System.out.println(Thread.currentThread().getName()+"	第1次版本号:"+stamp);
                // 暂停3秒钟t2线程,保证t1完成了一次ABA操作
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                boolean result = atomicStampedReference.compareAndSet(100, 2019, stamp, stamp+1);
                System.out.println(Thread.currentThread().getName()+"	执行结果:"+result+"	最新版本号:"+atomicStampedReference.getStamp());
                System.out.println(Thread.currentThread().getName()+"	当前实际最新值:"+atomicStampedReference.getReference());
            }, "t2").start();
        }
    }

    输出结果:

    t1    第1次版本号:1
    t2    第1次版本号:1
    t1    第2次版本号:2
    t2    执行结果:false    最新版本号:3
    t2    当前实际最新值:100
  • 相关阅读:
    [PAT] A1066 Root of AVL Tree
    [PAT] A1043 Is It a Binary Search Tree
    [PAT] A1053 Path of Equal Weight
    [PAT] A1038 Recover the Smallest Number
    [PAT] A1037 Magic Coupon
    [PAT] A1033 To Fill or Not to Fill (25分)
    Android开发 ---基本UI组件5:监听下拉选项,动态绑定下拉选项、全选/反选,取多选按钮的值,长按事件,长按删除,适配器的使用,提示查询数据,activity控制多按钮
    Android开发 ---基本UI组件4:拖动事件、评分进度条、圆圈式进度条、进度条控制
    Android开发 ---基本UI组件3:单选按钮、多选按钮、下拉列表、提交按钮、重置按钮、取消按钮
    Android开发 ---基本UI组件2:图像按钮、单选按钮监听、多选按钮监听、开关
  • 原文地址:https://www.cnblogs.com/MWCloud/p/11460721.html
Copyright © 2011-2022 走看看