CAS(比较并交换),它是一条CPU并发原语,它的功能是判断内存中某个位置的值是否和期望值一致,如果一致的话就去更该为新的值,这个过程是原子的。
Unsafe类中的compareAndSwapInt方法,是native方法能够实现原子操作的本质是硬件层面的。
CAS不需要加锁,但是也有缺点:
有些业务场景,仅仅只关注值是否一样是不够的,需要监控中间的值有没有变过,这时候就需要在修改之后也修改版本号了
ABA问题的复现和解决代码
package com.jin.javaLearning220114;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;
/**
* @author JinJian
* @version 1.0
* @date 2023/8/27 11:03
*/
public class ABATest01 {
private static AtomicReference<Integer> atomicReference = new AtomicReference(1);
//加上了时间戳
private static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(1,1);
public static void main(String[] args) {
System.out.println("+++++++++ABA问题的产生++++++++++++");
new Thread(() ->{
boolean b = atomicReference.compareAndSet(1, 2);
System.out.println(Thread.currentThread().getName() + "修改" + b + " atomicReference的值为" + atomicReference.get());
boolean b1 = atomicReference.compareAndSet(2, 1);
System.out.println(Thread.currentThread().getName() + "修改" + b1 + " atomicReference的值为" + atomicReference.get());
},"T1").start();
new Thread(() ->{
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
boolean b3 = atomicReference.compareAndSet(1, 6);
System.out.println(Thread.currentThread().getName() + "修改" + b3 + " atomicReference的值为" + atomicReference.get());
},"T2").start();
System.out.println("+++++++++ABA问题的解决++++++++++++");
new Thread(() ->{
System.out.println(Thread.currentThread().getName() + " 拿到" + " atomicStampedReference的版本号 " + atomicStampedReference.getStamp());
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
boolean b4 = atomicStampedReference.compareAndSet(1, 2, 1, atomicStampedReference.getStamp() + 1);
System.out.println(Thread.currentThread().getName() + " 修改" + b4 + " atomicStampedReference值 " + atomicStampedReference.getReference()+ " atomicStampedReference版本号是 " + atomicStampedReference.getStamp());
boolean b5 = atomicStampedReference.compareAndSet(2, 1, 2, atomicStampedReference.getStamp() + 1);
System.out.println(Thread.currentThread().getName() + " 修改" + b5 + " atomicStampedReference值 " + atomicStampedReference.getReference()+ " atomicStampedReference版本号是 " + atomicStampedReference.getStamp());
},"T3").start();
new Thread(() ->{
System.out.println(Thread.currentThread().getName() + " 拿到" + " atomicStampedReference的版本号 " + atomicStampedReference.getStamp());
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
boolean b6 = atomicStampedReference.compareAndSet(1, 2, 1, atomicStampedReference.getStamp() + 1);
System.out.println(Thread.currentThread().getName() + " 修改" + b6 + " atomicStampedReference值 " + atomicStampedReference.getReference()+ " atomicStampedReference版本号是 " + atomicStampedReference.getStamp());
},"T4").start();
}
}