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