Java内存模型:编译器重新排列代码行

Bha*_*kar 7 java memory memory-model

众所周知,只要重新排序对代码语义没有区别,Java语言允许编译器重新排列编译代码行.但是,编译器只需要打扰从当前线程看到的sematics .如果此重新排序影响多线程情况下的语义,则通常会导致并发问题(内存可见性)

我的问题:

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

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

Pet*_*rey 8

javac编译器旁边没有的优化执行.

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

通过将这个freedm允许编译器实现了什么?

主要好处是代码可移植性.您提供的保证越多,确保每个平台实际执行此操作的难度就越大.

通过允许CPU在可能的情况下执行指令而不是严格的顺序,也可以显着提高性能.

编译器是否真的可以通过重新排列代码来生成更高效的代码?

是.但CPU完成的重新排序更为重要.

我还没有看到一个实际案例.我觉得有时可以带来的好处远远超过这可能带来的并发风险.

程序员有没有办法告诉编译器不要重新排列这样的行?

这就是为什么你使用像块volatile,synchronized块和Lock.当您使用这些时,您将获得线程安全保证.

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

您可以关闭JIT,但大多数重新排序都是由CPU完成的,所以它不会实现太多.

避免重新排序更新是线程安全问题的一小部分(其最大的问题是模糊不清,很少发生,这使得测试很难)而且一旦编写线程安全代码,这就会得到缓解.