JVM(五) happens-before、as-if-serial

112 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

happens-before

两个动作(action)可以被 happens-before 关系排序。如果一个动作 happens-before 另一个动作,则第一个对第二个可见,且第一个排在第二个之前。必须强调的是,两个动作之间存在 happens-before 关系并不意味着这些动作在 Java 中必须以这种顺序发生。happens-before 关系主要用于强调两个有冲突的动作之间的顺序,以及定义数据争用的发生时机。可以通过多种方式包含一个happens-before 顺序,包括:

1.某个线程中的每个动作都 happens-before 该线程中该动作后面的动作。
2.某个管程上的 unlock 动作 happens-before 同一个管程上后续的 lock 动作。
3.对某个 volatile 字段的写操作 happens-before 每个后续对该 volatile 字段的读操作。
4.在某个线程对象上调用 start()方法 happens-before 该启动了的线程中的任意动作。
5.某个线程中的所有动作 happens-before 任意其它线程成功从该线程对象上的join()中返回。
6.如果某个动作 a happens-before 动作 b,且 b happens-before 动作 c,则有 a happens-before c

image.png 如图,对同一个程序的不同执行路径中,b的执行对x的冲突访问没用happens-before顺序,因此这个程序是未同步的。

as-if-serial

as-if-serial语义的意思指:不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。编译器,runtime 和处理器都必须遵守as-if-serial语义。

double pi = 3.14; //A 
double r = 1.0; //B 
double area = pi * r * r; //C

此处A与C有依赖关系,B与C也有依赖关系,但是A与B并没有依赖关系。此处就是需要无论先执行A还是先执行B,最终的结果都一样。

image.png

as-if-serial语义把单线程程序保护了起来,遵守as-if-serial语义的编译器,runtime 和处理器共同为编写单线程程序的程序员创建了一个幻觉:单线程程序是按程序的顺序来执行的。as-if-serial语义使单线程程序员无需担心重排序会干扰他们,也无需担心内存可见性问题。 、