ABA问题
ABA问题
问题现象:两个线程都去获取一个值,第一个线程获取后将其改变,然后又改回来,第二个线程获取到之后以为是第一个值,继续执行下去
ABA问题示例
package com.example.juc;
import java.util.concurrent.atomic.AtomicInteger;
public class TestCas {
    public static void main(String[] args) {
        AtomicInteger atomicInteger = new AtomicInteger(2021);
        int andIncrement = atomicInteger.getAndIncrement();
        System.out.println(atomicInteger.compareAndSet(2022, 2023));
        System.out.println(atomicInteger.compareAndSet(2023, 2022));
        System.out.println(atomicInteger);
        System.out.println(atomicInteger.compareAndSet(2022, 2022));
        System.out.println(atomicInteger);
    }
}
true
true
2022
true
2022
解决方案:带版本号的CAS
package com.example.juc;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;
public class TestAba {
    public static void main(String[] args) {
        Integer integer = 1;
        Integer integer1 = 2;
        AtomicStampedReference<Integer> iasr = new AtomicStampedReference<>(integer, 1);
        int stamp = iasr.getStamp();
        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(iasr.compareAndSet(1, 2, iasr.getStamp(), iasr.getStamp() + 1));
            System.out.println(iasr.compareAndSet(2, 1, iasr.getStamp(), iasr.getStamp() + 1));
        }).start();
        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(iasr.compareAndSet(1, 2, stamp, iasr.getStamp() + 1));
        }).start();
    }
}
true
false
true
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号