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 版权协议,转载请附上原文出处链接和本声明。