我知道下一个场景:(奇怪的格式,我知道)
private final AtomicBoolean aBoolean = new AtomicBoolean(true);
public void doSomething() {
if (
aBoolean.get() // line A
&& // line B
aBoolean.compareAndSet(true, false) // line C
) {
System.out.println("Was true!")
}
}
如果线程#1 和线程#2doSomething()
恰好同时进入,这将发生:
线程 #1 和线程 #2 将
aBoolean.get()
同时读取为 == "true"。两者都将执行“&&”运算符。
CMPXCHG 指令同时为两个线程启动:
3.1 本地使用LOCK前缀
3.2 线程#1 或#2 先到达,赢得比赛。
3.3 获胜线程比较(aBoolean == true 吗?)这将返回“true”,因此 aBoolean 将设置为“false”。
3.4 aBoolean 现在是假的。
3.5 丢失线程比较(是 aBoolean == true 吗?)这将返回“false”,因此会短路任何进一步的操作。
获胜线程将打印“是真的!”。
在“失败”线程的角度下,“ aBoolean.get()
A 线”中的第一个是......假设......一个“谎言”。
现在假设执行可以发生在操作符之间,就像上面例子中所做的那样,让我们为第二种情况添加第二种方法:
public void unluckySet() {
aBoolean.set(false);
}
假设线程#3恰好unluckySet()
在我们的“获胜线程”到达“&&”正在执行的“B行”的确切时刻到达并执行。
如果获胜线程到达“B 行”,则意味着它到达“A 行”,aBoolean 为“真”。
我的问题是:
CMPXCHG 是否会将更新后的值正确读取为“假”?这意味着.set()
也由与 . 相同的锁持有compareAndSet()
。
在并发和线程之间:
运算符(“&&”、“||”、“==”、“=”,甚至可能是“return;”?以交错方式结束,防止可能的冲突?