Java JIT编译器优化 - 就volatile变量值缓存而言JIT是否一致?

时间:2016-05-20 13:47:54

标签: java concurrency volatile jit

我正在努力更好地理解JIT编译器在易失性变量值缓存方面如何为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;
}

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

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

2 个答案:

答案 0 :(得分:3)

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

然而,JIT可能会优化循环并将其转换为无限循环,因为布尔标志未在循环内设置,这与从缓存中读取过时值无关。

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

答案 1 :(得分:2)

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

JVM使用启发式方法来决定何时在不同的优化级别编译或重新编译方法;所讨论的优化可能仅发生在特定的优化级别。 JIT编译器始终存在一定程度的可变性。