代码在编译阶段,编译器可能会进行重排序(Java 在编译期字节码是按代码顺序生成的,但 JIT 执行时就不保证顺序了)

代码在执行阶段,CPU 也可能会重排指令(CPU 的乱序执行,忽略不看)

比如下面这段代码

int a = a1; // a1 = 1;
double b = b1; // b1 = 0.1;

Java 的 JIT 在执行时,并不会保证:对 "a" 内存的写入一定在对 "b1" 内存的读取之前发生

并且,因为 "整形" 和 "浮点型" 用的运算器不同,还是可能被重排的

as-if-serial 规则

as-if-seria指令重排l 的意思是,编译器、处理器、JIT 等为了提高并行度,所有的动作(Action)都可以为了优化,而被重排序

但是,不管怎么重排序,单个线程的执行结果不能被改变。

为了遵守 "as-if-serial" 语义,编译器和处理器不会对存在 "数据依赖关系" 的操作做重排序

一个硬性规定,忽略

Java 的 happens-before 规则

准确来说是 Java 内存模型中的规则,JSR-133 使用 happens-before 的概念来指定两个操作之间的执行顺序

如果 A happens-before B,那么 Java 内存模型将向程序员保证:A 操作的结果将对 B 可见,且 A 的执行顺序排在 B 之前

至于网上罗列的几条规则,都是根据 Java 内存模型总结出来的,不用刻意去记。重点理解 volatile 关键字的作用即可

详情可以查看 Doug Lea 写给编辑器开发者的文章:The JSR-133 Cookbook for Compiler Writers

参考资料