happens-before定义了这么多规则,其实总结起来可以归纳为一句话:happens-before规则保证了单线程和正确同步的多线程的执行结果不会被改变。
那为什么有程序次序规则的保证,上面多线程执行过程中还是出现了重排序呢?这是因为happens-before规则仅仅是java内存模型向程序员做出的保证。在单线程下,他并不关心程序的执行顺序,只保证单线程下程序的执行结果一定是正确的,java内存模型允许编译器和处理器在happens-before规则下对程序的执行做重排序。
而且从程序员角度来说,对于两个操作是否真的被重排序并不关心,关心的是程序执行结果是否被改变。
上面的程序在单线程会被重排序的情况下又没有对多线程同步,这样就导致了意料之外的结果。
《Java并发编程的艺术》中解释:
as-if-serial就是不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。编译器、runtime和处理器都必须遵守as-if-serial语义。
这句话通俗理解就是as-if-serial语义保证单线程程序的执行结果不会被改变。
本质上和happens-before规则是一个意思:happens-before规则保证了单线程和正确同步的多线程的执行结果不会被改变。都是对执行结果做保证,对执行过程不做保证。
这也是JMM设计上的一个亮点:既保证了程序员编程时的方便以及正确,又同时保证了编译器和处理器更大限度的优化自由。
参考资料:
《深入理解Java内存模型》
《深入理解Java虚拟机》
《Java并发编程的艺术》