-
只有热点代码才有重排序的风险
热点代码是指被频繁执行的代码片段,由于它的重要性,JVM 会对其进行特殊优化,如 JIT 后段编译等。但是,热点代码在执行过程中存在着重排序的风险,这可能会导致程序的行为出现问题。
-
volatile的防止重排序是 jit 完成的,本质是 jit 加入了当前环境 cpu 能识别的 loadload 和 storestore 屏障
为了避免热点代码的重排序问题,Java提供了 volatile 关键字来保证内存的可见性和禁止重排序。在实现中,JIT编译器会加入当前环境 cpu 能识别的 loadload 和 storestore 屏障指令,这些指令都是 cpu 指令,可以命令 cpu 停止指令重排和分支预测。
-
CPU发现这些屏障指令,会立刻停止重排序和预测
当CPU执行到屏障指令时,会暂停当前的执行流程,等待内存操作完成(本质是 cpu 上的加锁,比如总线索这种,这也就保证了 volatile 的可见性),此外会下令禁止指令的重排序,然后再继续执行。这样能够保证内存操作的有序性,同时避免了CPU进行重排序和预测的风险。
-
一般情况下,单例构造器这种非热点代码是解释执行的,不需要考虑因为重排序导致的构造器逃逸的问题
对于一些非热点代码,如单例构造器等,由于其执行频率较低,JVM通常会采用解释执行的方式来运行,这样就不需要考虑重排序问题。但是,如果这些代码在程序中被频繁调用,就有可能变成热点代码,此时就需要注意重排序的问题。
总之,了解热点代码重排序的原理对于编写高效且正确的Java程序非常重要,我们需要合理地使用volatile关键字来避免重排序问题的出现,并对程序的运行情况进行监控和优化。