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问题代码详解
最新推荐文章于 2023-10-06 20:45:47 发布