目录
- 一、代码示例
- 二、执行结果截图
- 三、说明
- 四、AtomicStampedReference使用
-
一、代码示例
package com.learning.atomic;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.atomic.AtomicReference;
/**
* @Author wangyouhui
* @Description ABA问题
**/
@Slf4j
public class AtomicReferenceABA {
static AtomicReference<String> reference = new AtomicReference<>("A");
public static void main(String[] args) {
String previous = reference.get();
otherThreadExecute();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("A->C:{}",reference.compareAndSet(previous, "C"));
}
private static void otherThreadExecute() {
new Thread(()->{
log.info("A->B:{}", reference.compareAndSet(reference.get(), "B"));
}).start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
log.info("B->A:{}",reference.compareAndSet(reference.get(), "A"));
}).start();
}
}
二、执行结果截图
三、说明
- 1.主线程准备将共享变量由A改为C
- 2.在这期间,线程1将共享变量由A改为B,线程2再将共享变量B改为A
- 3.对于主线程仅能判断出共享变量的值与最初值A是否相同,不能感知到A改为B又改回A的情况
- 4.如果希望主线程能感知到其它线程动过该共享变量,则cas失败,所以比较值是不能解决问题的,需要再加一个版本号
- 5.AtomicStampedReferennce
四、AtomicStampedReference使用
4.1 代码示例
package com.learning.atomic;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.atomic.AtomicStampedReference;
/**
* @Author wangyouhui
* @Description AtomicStampedReference解决ABA问题
**/
@Slf4j
public class AtomicStampedReferenceABA {
static AtomicStampedReference<String> reference = new AtomicStampedReference("A", 0);
public static void main(String[] args) {
// 主线程获取值
String previous = reference.getReference();
// 主线程获取版本号
int stamp = reference.getStamp();
log.info("主线程获取版本号:{}", stamp);
otherThreadExecute();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("主线程获取版本号:{}", reference.getStamp());
log.info("A->C:{}",reference.compareAndSet(previous, "C", stamp, stamp+1));
}
private static void otherThreadExecute() {
new Thread(()->{
int stamp = reference.getStamp();
log.info("线程1获取版本号:{}", stamp);
log.info("A->B:{}", reference.compareAndSet(reference.getReference(), "B", stamp, stamp + 1));
}).start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
int stamp = reference.getStamp();
log.info("线程2获取版本号:{}", stamp);
log.info("B->A:{}",reference.compareAndSet(reference.getReference(), "A", stamp, stamp + 1));
}).start();
}
}
4.2 截图