ABA问题,原子引用问题

  • Post author:
  • Post category:其他




ABA问题:

CAS操作可能带来ABA问题,因为CAS操作需要在操作值的时候,检查值有没有发生变化,如果没有发发生变化则更新。如果一个值原理是A,变成了B,又变成了A,那么使用CAS进行检查时会认为它的值没有变化,但是实际上却变了。

ABA问题的解决办法就是使用版本号,在变量前面追加版本号,每次变量更新时把版本号加1,那么A-B-A就会变成1A-2B-3A。

从jdk1.5开始,jdk中的Atomic包里提供了一个类AtomicStampedReference来解决ABA问题。这个类的compareAndSet方法的作用首先检查当前引用是否等于预期引用,并且检查当前标志是否等于预期标志,如果都相等,则以原子方式将该引用和标志的值设为给定的更新值。

public class ABAtestDemo {

    //初始值,版本号
    static AtomicStampedReference<Integer> atomicStampedReference=new AtomicStampedReference<>(100,1);
    public static void main(String[] args) {
        System.out.println("=============以下是ABA问题的解决===============");
        new Thread(()->{
            //获取版本号1
            int stamp=atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t 第1次版本号:"+stamp);

            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()+"\t 第2次版本号:"+atomicStampedReference.getStamp());
            atomicStampedReference.compareAndSet(101,100,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println(Thread.currentThread().getName()+"\t 第2次版本号:"+atomicStampedReference.getStamp());
        },"t3").start();

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

            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            boolean b = atomicStampedReference.compareAndSet(100, 2019, stamp, stamp + 1);
            System.out.println(Thread.currentThread().getName()+"\t修改成功否:"+b+"\t 当前最新实际版本号:"+atomicStampedReference.getStamp());
            System.out.println(Thread.currentThread().getName()+"\t当前实际最新值::"+atomicStampedReference.getReference());
        },"t4").start();
    }

}



原子引用问题:

class User {

    String username;
    int age;


    public User(String username, int age) {
        this.username = username;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", age=" + age +
                '}';
    }
}

public class AutomicReferenceImport {

    public static void main(String[] args) {
        User z3 = new User("z3", 23);
        User li4 = new User("li4", 24);

        AtomicReference<User> atomicReference = new AtomicReference();
        atomicReference.set(z3);

        System.out.println(atomicReference.compareAndSet(z3,li4)+"==="+atomicReference.get().toString());
        System.out.println(atomicReference.compareAndSet(z3,li4)+"==="+atomicReference.get().toString());
    }
}



版权声明:本文为qq_43459184原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。