【问题标题】:The implementation difference between the interperter and the JIT compiler for AtomicInteger.lazySet() in the Hotspot JVMHotspot JVM中AtomicInteger.lazySet()的interperter和JIT编译器的实现区别
【发布时间】:2021-07-19 23:30:04
【问题描述】:

有关 AtomicInteger.lazySet() 的背景,请参阅AtomicInteger lazySet vs. set 的现有讨论。

所以根据 AtomicInteger.lazySet() 的语义,在 x86 CPU 上,AtomicInteger.lazySet() 相当于对 AotmicInteger 的值进行正常的写操作,因为 x86 内存模型保证了写操作之间的顺序。

但是,AtomicInteger.lazySet() 的运行时行为在 JDK 8 Hotspot JVM 中的 interperter 和 JIT 编译器(特别是 C2 编译器)之间是不同的,这让我很困惑。

首先,为演示创建一个简单的 Java 应用程序。

import java.util.concurrent.atomic.AtomicInteger;

public class App {
    public static void main (String[] args) throws Exception {
        AtomicInteger i = new AtomicInteger(0);
        i.lazySet(1);
        System.out.println(i.get());
    }
}

然后,转储来自 C2 编译器提供的 instrinc 方法的 AtomicInteger.lazySet() 指令:

$ java -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -XX:CompileCommand=print,*AtomicInteger.lazySet App
...
      0x00007f1bd927214c: mov    %edx,0xc(%rsi)     ;*invokevirtual putOrderedInt
                                                ; - java.util.concurrent.atomic.AtomicInteger::lazySet@8 (line 110)

如您所见,操作正如预期的正常写入。

然后,使用 GDB 跟踪 AtomicInteger.lazySet() 解释器的运行时行为。

$ gdb --args java App
(gdb) b Unsafe_SetOrderedInt

0x7ffff69ae836 callq  0x7ffff69b6642 <OrderAccess::release_store_fence(int volatile*, int)>     

0x7ffff69b6642: 
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    -0xc(%rbp),%eax
mov    -0x8(%rbp),%rdx
xchg   %eax,(%rdx)           // the write operation
mov    %eax,-0xc(%rbp)
nop
pop    %rbp
retq

你可以看到,操作实际上是一个XCHG指令,它具有隐含锁语义,它带来了AtomicInteger.lazySet() 旨在消除的性能开销。

有谁知道为什么会有这样的差异?谢谢。

【问题讨论】:

    标签: concurrency jvm atomic


    【解决方案1】:

    在解释器中优化一个很少使用的操作没有多大意义。这会增加开发和维护成本而没有明显的好处。

    仅在 JIT 编译器(C2 或 C1+C2)中实现优化是 HotSpot 的常见做法。解释器实现只是工作,它不需要很快,因为如果代码是性能敏感的,它无论如何都会被 JIT 编译。

    因此,在解释器中(即在慢速路径上),Unsafe_SetOrderedInt 与 volatile 写入完全相同。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    • 1970-01-01
    • 2016-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多