有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

是JAVA中的原子操作

if (!var) {...}

上述内容是否会被扩展为类似的内容

  • 将var的值加载到寄存器R中
  • 设置R=!R

或者是只有一个操作的原子

  • 加载值!输入寄存器R

共 (2) 个答案

  1. # 1 楼答案

    不,不可能

    考虑以下两种情况:

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

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

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

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

  2. # 2 楼答案

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

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

    编辑:以上是如何将代码编译成字节码。就同步而言,出于实际目的,它是原子的。由于代码是纯本地的,因此通常无法观察副作用,也无法让计算干扰其他线程。请注意,即使加载一个未同步的字段,该值也会变成一个中间值(即“寄存器”),并对该值执行操作,而该值不会在线程之间共享。除了读和写之外,没有任何操作直接发生在字段上

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