是! JAVA中的操作原子

时间:2016-12-09 02:26:59

标签: java atomic bytecode

if (!var) {...}

上述内容是否会用于

之类的内容
  • 将var的值加载到寄存器R
  • 设置R =!R

或者只有一次操作的原子

  • 将!var的值加载到寄存器R

2 个答案:

答案 0 :(得分:4)

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

例如,如果您编写类似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

编辑:以上是代码如何编译成字节码。就同​​步而言,它是实用的原子。由于代码纯粹是局部的,因此通常无法观察副作用或计算干扰其他线程。请注意,即使您加载了一个非同步字段,该值也会成为一个中间值(即“寄存器”),并且该值会发生操作,而这些值不会在线程之间共享。除了读取和写入之外的字段上不会直接执行任何操作。

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

答案 1 :(得分:1)

没有。它不可能。

考虑以下两种情况:

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

VS

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

最终结果是相同的 - 在这两种情况下,寄存器包含的值都不同于!A。负荷反转操作的“原子”性质对结果完全没有影响。

如果这似乎可能造成问题,您可能需要锁定。考虑在A上或在其所在的容器上进行同步。