是 ! JAVA 中的原子操作
Is ! operation atomic in JAVA
if (!var) {...}
以上是否扩展成类似
的东西
- 将 var 的值加载到寄存器 R
- 设置 R = !R
或者只有一个操作的原子
- 将 !var 的值加载到寄存器 R
没有。不可能。
考虑以下两种情况:
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"),并且会对该值进行操作,该值不会在线程之间共享。除了读取和写入之外,没有直接在字段上发生任何操作。
也就是说,由于代码涉及多个字节码指令,您可以在其中停止调试器。在那种情况下,您可以观察到中间状态,尽管它仍然对其他线程没有影响。
if (!var) {...}
以上是否扩展成类似
的东西- 将 var 的值加载到寄存器 R
- 设置 R = !R
或者只有一个操作的原子
- 将 !var 的值加载到寄存器 R
没有。不可能。
考虑以下两种情况:
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"),并且会对该值进行操作,该值不会在线程之间共享。除了读取和写入之外,没有直接在字段上发生任何操作。
也就是说,由于代码涉及多个字节码指令,您可以在其中停止调试器。在那种情况下,您可以观察到中间状态,尽管它仍然对其他线程没有影响。