【问题标题】:Java JIT compiler optimizations - is JIT consistent in respect to volatile variables value caching?Java JIT 编译器优化 - JIT 在 volatile 变量值缓存方面是否一致?
【发布时间】:2016-09-17 19:39:57
【问题描述】:

我试图更好地理解 JIT 编译器在 volatile 变量值缓存方面如何为 java 工作。 考虑这个问题中提出的例子: Infinite loop problem with while loop and threading:

boolean loaded = false; // not volatile!!!
private boolean loadAsset() {
    new Thread(new Runnable() {

        @Override
        public void run() {

            // Do something
            loaded = true;

        }
    }).start();

    while (!loaded) {
        System.out.println("Not Loaded");
    }
    System.out.println("Loaded");
    return false;
}

由于变量 loaded 未声明为 volatile,JIT 编译器允许“缓存”注册表中的变量。据说这在理论上可能会导致无限循环,因为执行循环的线程可能在某个时间点看不到变量是从另一个线程更新的。

但是“允许”缓存到底是什么意思呢?变量是否有可能被缓存sometimes,这意味着如果我在同一个 JVM 中运行同一段代码(不关闭 JVM)一百万次,JIT 编译器可能会在某个时候决定缓存变量并产生无限循环?还是 JIT 编译器是一致的,这意味着它要么决定缓存变量,要么不缓存该变量,并且该决定将在 JVM 的整个生命周期中对这段代码的所有数百万次执行保持不变?

【问题讨论】:

  • 据我所知(至少在纯 Java 中),您和 JVM 都没有直接控制缓存。缓存由硬件 (CPU) 控制。根据某些因素,缓存中的变量会被覆盖、失效、更新等……因此,变量可能只在某些时候被缓存。但是通过使用volatile,您可以指示 JVM(以及 CPU)永远不要使用缓存值,而是使用内存值。我不知道volatile是停用缓存还是只指示每次都从内存中读取值。
  • @Turing85:您的评论完全错误;提问者答对了。 HotSpot 优化器可能会发出将值保存在 CPU 寄存器中的本机代码,而不是从堆中重新读取它们。这与缓存具有相同的效果,事实上,在 x86 上,这是内存可见性问题的主要原因,因为真正的 CPU 缓存在该平台上是一致的。

标签: java concurrency volatile jit


【解决方案1】:

这里的缓存发生在硬件级别,CPU 可能决定从其缓存中读取变量的值,而丢弃其他线程在自己的缓存中写入的内容。

但是,JIT 可能会优化循环并将其变成无限循环,因为循环内未设置布尔标志,这与从缓存中读取陈旧值不同。

允许缓存”在这里可能被解释为,JIT 没有义务在读取变量时发出fence instruction

【讨论】:

  • 这几乎回答了我的问题。我仍然不明白的是,JIT 是否有可能决定在某个时间点“优化”循环?意思是,程序是否有可能在一段时间内运行并在几分钟/小时后 JIT 将缓存一个值?
  • @mdzh 请阅读我的评论。编译器不缓存任何东西。硬件决定什么被缓存,什么不被缓存。
  • @mdzh 问题是缓存是一种有限的资源,驱逐或保留在缓存中由 CPU 控制,但是 JIT 可以要求 CPU 每次都无效并获取一个新值。因此,可能在某个时候该值被逐出并读取了新副本。
  • @mdzh:是的,JIT 可以在任意时间点优化循环,不受您的控制。这个决定受到很多事情的影响。最值得注意的是,它在较旧的 JVM 中并不像在最近的 JVM 中那样经常发生。
【解决方案2】:

要回答您的最后一个问题,是的,JIT 可能会在程序运行一段时间后决定以这种方式优化循环。

JVM 采用启发式方法来决定何时在不同的优化级别编译或重新编译方法;有问题的优化可能只发生在特定的优化级别。 JIT 编译器总是存在一定程度的可变性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-21
    • 2015-09-03
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    • 2013-02-26
    • 2015-12-25
    相关资源
    最近更新 更多