【问题标题】:Java memory model : compiler rearranging code linesJava 内存模型:编译器重新排列代码行
【发布时间】:2012-01-05 12:14:17
【问题描述】:

众所周知,Java 语言允许编译器重新排列已编译代码的行,只要重新排序对代码语义没有影响。然而,编译器只需要关心从当前线程中看到的语义。如果这种重新排序在多线程情况下影响语义,通常会导致并发问题(内存可见性)

我的问题:

  1. 允许编译器释放这个 freedm 可以实现什么?编译器真的有可能通过重新排列代码来生成更高效的代码吗?我还没有看到一个实际的案例。有时我觉得这样做带来的并发风险远远超过了好处。

  2. 程序员有什么办法可以告诉编译器不要像这样重新排列行?我知道使用同步原语可以有效地处理重新排列的副作用,但我想问是否有任何直接的方法(编译器选项)来关闭它?

【问题讨论】:

    标签: java memory memory-model


    【解决方案1】:

    javac 编译器几乎没有进行任何优化。

    JIT 本机编译器可以在存在内存排序问题的情况下重新排序指令。但是,CPU 也可以重新排序指令和内存更新,具有相同的效果。

    允许编译器释放这个freedm可以实现什么?

    主要好处是代码可移植性。您提供的保证越多,就越难以确保每个平台都真正做到这一点。

    通过允许 CPU 尽可能地执行指令而不是按照严格的顺序执行指令,还可以显着提高性能。

    编译器真的有可能通过重新排列代码来生成更高效的代码吗?

    是的。但 CPU 进行的重新排序更为重要。

    我还没有看到这方面的实际案例。有时我觉得这可能带来的并发风险远远超过了好处。

    程序员有什么办法可以告诉编译器不要像这样重新排列行吗?

    这就是你使用volatilesynchronized 块和Lock 之类的内存屏障的原因。当您使用这些时,您将获得线程安全保证。

    我知道使用同步原语可以有效地处理重新排列的副作用,但我想问是否有任何直接的方法(编译器选项)来关闭它?

    您可以关闭 JIT,但大多数重新排序是由 CPU 完成的,因此效果不大。

    避免重新排序更新只是线程安全问题的一小部分(其最大的问题是晦涩难懂且很少发生,这使得测试变得困难)一旦编写线程安全代码,这种情况就会得到缓解。

    【讨论】:

      【解决方案2】:

      重新排列字节码的过程由 JIT(即时编译器)管理。您可以使用以下选项阻止它运行:

      -Djava.compiler=NONE
      

      在此处查看更多信息:http://www.cs.swarthmore.edu/~newhall/unixhelp/debuggingtips_Java.html

      【讨论】:

      • 这不会停止 CPU 重新排序指令。 ;)
      • 而且它会让你的程序运行得非常慢,所以这不是一个对任何生产使用都有用的选项。
      【解决方案3】:

      编译器真的有可能通过重新排列代码来生成更高效的代码吗?

      哦,是的!

      现代计算机架构中的一个重要事实是内存是主要的性能瓶颈。 CPU 执行寄存器到寄存器指令的速度比它读取和写入主存储器的速度快很多倍。这就是为什么高性能芯片具有 2 或 3 级内存缓存的原因。此外,典型的 CPU 使用流水线允许多条指令同时在执行过程中。

      要充分利用具有这些属性的 CPU 的性能,编译器(以及 CPU 本身)需要能够对指令重新排序,以充分利用内存带宽,并保持流水线满载。本机代码还需要能够使用保存在寄存器中的值(变量),并尽量减少等待内存写入传播到主内存的内存屏障指令的使用。仅允许这些(在 Java 中),因为 Java 内存模型允许重新排序。

      注意:我们在这里谈论的是显着的加速:可能是 3 到 5 倍的加速。

      如果您想了解多少,请使用一个实例变量密集型应用程序并重写它,以便所有实例变量都是volatile。 (这将减少重新排序的范围,并导致所有读取和写入都进入内存。)然后将原始应用程序的性能与修改后的版本进行基准测试。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-12
        • 2011-02-04
        • 1970-01-01
        • 1970-01-01
        • 2016-10-10
        • 1970-01-01
        相关资源
        最近更新 更多