CAS是什么?
比较并交换CompareAndSwap,原子操作类的compareAndSet方法底层就是用了CAS,如果想修改某个原子类对象A的值,(对象A的值在底层是用参数ValueOffSet来存储的),compareAndSet方法的参数是except值与update值,传入之后调用unsafe的CAS方法,将except值与内存中的值相互比较,如果A与except值相等的话就修改A为update值并且返回Ture,否则就不修改返回false
见代码!
UnSafe类
提供了硬件级别的原子性操作,Java不能直接访问底层操作系统,UnSafe类是Java访问底层操作系统的入口
什么是ABA问题?
x y
线程1 except A,update B
线程2 except A, update B
线程3 except B, update A
线程执行顺序为 1x、2x、1y、3x、3y、2y结果为A—>B->A->B
去银行取钱,某个动作点击了两次,比如余额为 100 取钱 50 动作点击了两次,分别为线程1,2,此时某人汇钱给此账户 50 元为线程3按照上边的顺序执行后结果为 50元,显然是错误的,应该是100元。加个版本号可以解决问题。
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;
/**
* Function:演示CAS比较并交换的案例
* ABA问题
* x y
* 线程1 except A,update B
* 线程2 except A, update B
* 线程3 except B, update A
* 线程执行顺序为 1x、2x、1y、3x、3y、2y结果为A—>B->A->B
* 去银行取钱,某个动作点击了两次,比如余额为 100 取钱 50 动作点击了两次,分别为线程1,2,此时某人汇钱给此账户 50 元为线程3按照上边的顺序执行后结果为 50元,显然是错误的,应该是100元
* 加个版本号可以解决问题。
*
*
* @author liubing
* Date: 2019/5/30 7:11 PM
* @since JDK 1.8
*/
public class CASDemo {
//余额为100
static volatile AtomicInteger atomicInteger = new AtomicInteger(100);
static volatile AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<Integer>(100,0);
public static void main(String args[]){
// System.out.println("ABA问题");
// ABAQuestion();
// System.out.println("ABA问题解决方案");
// ABAAnswer();
}
public static void ABAQuestion(){
//取钱50线程1
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"线程修改100为50的结果是"+atomicInteger.compareAndSet(100,50));
},"1").start();
//取钱50线程2
new Thread(()->{
while(!atomicInteger.compareAndSet(100,50)){
}
System.out.println(Thread.currentThread().getName()+"线程修改100为50的结果是"+true);
System.out.println(Thread.currentThread().getName()+"线程查看结果为"+atomicInteger.get());
},"2").start();
//汇钱50
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"线程修改50为100的结果是"+atomicInteger.compareAndSet(50,100));
},"3").start();
}
public static void ABAAnswer(){
//取钱50线程1
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"线程修改100为50的结果是"+atomicStampedReference.compareAndSet(100,50,0,1));
},"1").start();
//取钱50线程2
new Thread(()->{
Boolean flag = true;
int sum = 0;
while(!atomicStampedReference.compareAndSet(100,50,0,1)){
sum++;
if(sum==10000){
flag = false;
break;
}
}
System.out.println(Thread.currentThread().getName()+"线程修改100为50的结果是"+flag);
System.out.println(Thread.currentThread().getName()+"线程查看结果为"+atomicStampedReference.getReference());
},"2").start();
//汇钱50
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"线程修改50为100的结果是"+atomicStampedReference.compareAndSet(50,100,1,2));
},"3").start();
}
}
ABA问题代码详解
CAS原理及ABA问题解决方案
最新推荐文章于 2025-07-21 12:41:16 发布
235





