当前位置:网站首页>JUC原子引用与ABA问题
JUC原子引用与ABA问题
2022-06-13 09:00:00 【Q z1997】
JUC原子引用
- AtomicReference
- AtomicMarkableReference
- AtomicStampedReference
class DecimalAccountSafeCas implements DecimalAccount {
AtomicReference<BigDecimal> ref;
public DecimalAccountSafeCas(BigDecimal balance) {
ref = new AtomicReference<>(balance);
}
@Override
public BigDecimal getBalance() {
return ref.get();
}
@Override
public void withdraw(BigDecimal amount) {
while (true) {
BigDecimal prev = ref.get();
BigDecimal next = prev.subtract(amount);
if (ref.compareAndSet(prev, next)) {
break;
}
}
}
}
ABA 问题及解决
ABA 问题
static AtomicReference<String> ref = new AtomicReference<>("A");
public static void main(String[] args) throws InterruptedException {
log.debug("main start...");
// 获取值 A
// 这个共享变量被它线程修改过?
String prev = ref.get();
other();
sleep(1);
// 尝试改为 C
log.debug("change A->C {}", ref.compareAndSet(prev, "C"));
}
private static void other() {
new Thread(() -> {
log.debug("change A->B {}", ref.compareAndSet(ref.get(), "B"));
}, "t1").start();
sleep(0.5);
new Thread(() -> {
log.debug("change B->A {}", ref.compareAndSet(ref.get(), "A"));
}, "t2").start();
}
主线程仅能判断出共享变量的值与最初值 A 是否相同,不能感知到这种从 A 改为 B 又 改回 A 的情况,如果主线程希望:
只要有其它线程【动过了】共享变量,那么自己的 cas 就算失败,这时,仅比较值是不够的,需要再加一个版本号
AtomicStampedReference
static AtomicStampedReference<String> ref = new AtomicStampedReference<>("A", 0);
public static void main(String[] args) throws InterruptedException {
log.debug("main start...");
// 获取值 A
String prev = ref.getReference();
// 获取版本号
int stamp = ref.getStamp();
log.debug("版本 {}", stamp);
// 如果中间有其它线程干扰,发生了 ABA 现象
other();
sleep(1);
// 尝试改为 C
log.debug("change A->C {}", ref.compareAndSet(prev, "C", stamp, stamp + 1));
}
private static void other() {
new Thread(() -> {
log.debug("change A->B {}", ref.compareAndSet(ref.getReference(), "B",
ref.getStamp(), ref.getStamp() + 1));
log.debug("更新版本为 {}", ref.getStamp());
}, "t1").start();
sleep(0.5);
new Thread(() -> {
log.debug("change B->A {}", ref.compareAndSet(ref.getReference(), "A",
ref.getStamp(), ref.getStamp() + 1));
log.debug("更新版本为 {}", ref.getStamp());
}, "t2").start();
}
AtomicStampedReference 可以给原子引用加上版本号,追踪原子引用整个的变化过程,如: A -> B -> A -> C ,通过AtomicStampedReference,我们可以知道,引用变量中途被更改了几次。但是有时候,并不关心引用变量更改了几次,只是单纯的关心是否更改过,所以就有了AtomicMarkableReference

AtomicMarkableReference
class GarbageBag {
String desc;
public GarbageBag(String desc) {
this.desc = desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return super.toString() + " " + desc;
}
}
@Slf4j
public class TestABAAtomicMarkableReference {
public static void main(String[] args) throws InterruptedException {
GarbageBag bag = new GarbageBag("装满了垃圾");
// 参数2 mark 可以看作一个标记,表示垃圾袋满了
AtomicMarkableReference<GarbageBag> ref = new AtomicMarkableReference<>(bag, true);
log.debug("主线程 start...");
GarbageBag prev = ref.getReference();
log.debug(prev.toString());
new Thread(() -> {
log.debug("打扫卫生的线程 start...");
bag.setDesc("空垃圾袋");
while (!ref.compareAndSet(bag, bag, true, false)) {
}
log.debug(bag.toString());
}).start();
Thread.sleep(1000);
log.debug("主线程想换一只新垃圾袋?");
boolean success = ref.compareAndSet(prev, new GarbageBag("空垃圾袋"), true, false);
log.debug("换了么?" + success);
log.debug(ref.getReference().toString());
}
}
边栏推荐
- What are the bank financial products? How long is the liquidation period?
- 【网络安全渗透】如果你还不懂CSRF?这一篇让你彻底掌握
- Judgment of single exclamation point and double exclamation point in JS
- 20211115 任意n阶方阵均与三角矩阵(上三角或者下三角)相似
- Pytorch model tuning - only some layers of the pre training model are loaded
- A solution to create a new EXCEL workbook on win10 computer and change the suffix to xlsm (normally it should be xlsx)
- Diversified tables through TL table row consolidation
- 20211006 积分、微分、投影均属于线性变换
- Cesium displays a pop-up box at the specified position and moves with the map
- 20220524 如何把CoppeliaSim安装到D盘
猜你喜欢

教程篇(5.0) 03. 安全策略 * FortiEDR * Fortinet 网络安全专家 NSE 5

Print an array clockwise

Uni app subcontracting loading and optimization

Qvector shallow copy performance test

Basic use of cesium, including loading images, terrain, models, vector data, etc

20220606 关于矩阵的Young不等式

Diversified tables through TL table row consolidation

如何成为白帽子黑客?我建议你从这几个阶段开始学习

How excel adds hyperlinks to some text in a cell

Top+jstack to analyze the causes of excessive CPU
随机推荐
Common network problems and troubleshooting methods of gbase
13.inline,const,mutable,this,static
關於RSA加密解密原理
A very detailed blog about the implementation of bilinear interpolation by opencv
Mttr/mttf/mtbf diagram
Pytorch model tuning - only some layers of the pre training model are loaded
Opencv gaussianblur() explanation (Sigma value)
20211108 det(AB)=det(A)det(B)
Is it safe to open an account online? Can a novice open an account?
Object in ES6 Use of entries()
Collection of garbled code problems in idea development environment
redis
Tutorial (5.0) 01 Product introduction and installation * fortiedr * Fortinet network security expert NSE 5
【QNX Hypervisor 2.2 用户手册】4.5.1 构建QNX Guest
【网络安全渗透】如果你还不懂CSRF?这一篇让你彻底掌握
Pytorch same structure different parameter name model loading weight
Calculation method of paging
How to become a white hat hacker? I suggest you start from these stages
Brief description of software testing and software maintenance
20211020 段院士全驱系统