是 ! JAVA 中的原子操作

Is ! operation atomic in JAVA

if (!var) {...}

以上是否扩展成类似

的东西

或者只有一个操作的原子

没有。不可能。

考虑以下两种情况:

Thread 1                Thread 2
--------                --------
Load A to register      ...
...                     Modify A
Invert register         ...

对比

Thread 1                Thread 2
--------                --------
Atomically load !A      ...
    to register
...                     Modify A

最终结果是一样的——在这两种情况下,寄存器包含的值不同于!A。 "atomic" 负载反转操作的性质对结果完全没有影响。

如果这看起来会造成问题,您可能需要锁定。考虑在 A 或它所在的容器上进行同步。

没有对应逻辑非的字节码级操作。它通常会被编译为一个分支,尽管编译器有时可以优化它。

例如,如果您编写 b = !a 这样的代码,它通常会被编译成类似于

的代码
iload_0 ; load a
ifeq Lelse
iconst_0
goto Lend

Lelse:
iconst_1

Lend:
istore_1 ; store into B

但是在你提到的if (!var)的特殊情况下,这是没有必要的。这是因为 if 指令对于常规条件和反向条件都有变体,即编译器不会实际否定 var,而是使用 ifne 指令而不是通常的 ifeq.

编辑:以上是代码编译成字节码的过程。就同​​步而言,它在实际应用中是原子的。由于代码是纯本地的,通常没有办法观察副作用或计算干扰其他线程。请注意,即使您加载了一个未同步的字段,该值也会变成一个中间值(即 "register"),并且会对该值进行操作,该值不会在线程之间共享。除了读取和写入之外,没有直接在字段上发生任何操作。

也就是说,由于代码涉及多个字节码指令,您可以在其中停止调试器。在那种情况下,您可以观察到中间状态,尽管它仍然对其他线程没有影响。