说说什么是指令重排?
在不影响单线程程序执行结果的前提下,计算机为了最大限度的发挥机器性能,对机器指令进行重排序优化。
从Java源代码到最终实际执行的指令序列,会分别经历下面3种重排序:
- 编译器重排序:编译器在不改变单线程程序语义的前提下重新安排语句的执行顺序。例如把变量缓存到寄存器中、提取公共子表达式等。
- 指令级重排序:如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。例如乱序执行的 Load 和 Store 指令、分支预测以及指令突发等。
- 内存系统重排序:由于数据读写过程中涉及到多个缓冲区,这使得加载和存储的操作看上去可能是乱序执行,于是需要内存系统的重排序。例如写入缓存中的操作顺序,对于其他CPU的 Cache 来说是不可见的。
以双重校验锁单例模式为例子,Singleton instance=new Singleton();对应的JVM指令分为三步:分配内存空间-->初始化对象--->对象指向分配的内存空间,但是经过了编译器的指令重排序,第二步和第三步就可能会重排序。
JMM属于语言级的内存模型,它确保在不同的编译器和不同的处理器平台之上,通过禁止特定类型的编译器重排序和指令级重排序,为程序员提供一致的内存可见性保证。