使用关键字 volatile 可以禁止代码的重排序;
在 Java 程序运行时, JIT(即使编译器) 可以动态地改变程序代码运行地顺序; 例如, 有如下代码:
A 代码 - 重耗时
B 代码 - 轻耗时
C 代码 - 重耗时
D 代码 - 轻耗时
在多线程环境下, JIT 有可能进行代码重排序, 重排序后地代码顺序有可能如下:
B 代码 - 轻耗时
D 代码 - 轻耗时
A 代码 - 重耗时
C 代码 - 重耗时
这样做地主要原因是 CPU 流水线是同时执行这 4 个指令的, 那么轻耗时的代码在很大程度上先执行完成, 以让出 CPU 流水线给其他指令, 所以代码重排序是为了追求更高的程序运行的效率;
重排序发生在没有依赖关系时, 例如, 对于上面的 A,B,C,D 代码, B,C,D 代码不依赖 A 代码的结果, C,D 代码不依赖 A,B 代码的结果, D 代码不依赖 A,B,C 代码的结果, 这种情况下就会发生重排序, 如果代码之间有依赖关系, 则代码不会重排序;
使用关键字 volatile 可以禁止代码重排序, 例如, 有如下代码:
A 变量的操作
B 变量的操作
volatile Z 变量的操作
C 变量的操作
D 变量的操作
那么会有 4 种情况发生:
A,B 可以重排序
C,D 可以重排
A,B 不可以重排到 Z 的后面
C,D 不可以重排到 Z 的前面
换言之, 变量 Z 是一个屏障, Z 变量之前或之后不可以跨越 Z 变量, 这就是屏障的作用, 关键字 synchronized 具有同样的特性;
来源: http://www.bubuko.com/infodetail-3495819.html