数据依赖性
如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性。数据依赖分为下列三种类型:
上述三种情况,只要重排序两个操作的执行顺序,程序的执行结果将会被改变
只有编译器和处理器在重排序时会遵守数据依赖性,它们不会改变存在数据依赖性关系的两个操作的执行顺序。
但是不同处理器之间和不同线程之间的数据依赖性不被编译器和处理器考虑
as-if-serial
语义:不管怎么重排序,单线程程序的执行结果不能被改变。
如果操作之间不存在数据依赖关系,这些操作就可能被编译器和处理器重排序。
JSR-133内存模型
在JMM中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关系
1.程序顺序规则:一个线程中的操作,happens-before于该线程中的任意后续操作
2. 监视器锁规则:对一个监视器的解锁,happens-before与随后对这个监视器的加锁
3. volatile变量规则:对一个volatile域的写,happens-before与任意后续对这个volatile域的读
4. 传递性:如果A h-b B,且 B h-b C,那么 A h-b C
两个操作之间具有happens-before关系,并不意味着前一个操作必须要在后一个操作之后执行!
happens-before仅仅要求前一个操作的结果对后一个操作可见,且前一个操作按顺序排在第二个操作之前
程序顺序规则
根据happens-before的程序顺序规则,上面的实例代码存在三个happens-before关系:
1.A happens-before B
2.B happens-before C
3.A happens-before C
A happens-before C是推倒出来的
这里A happens-before B,但实际执行时B却可以排在A之前执行。
重排序A操作和B操作后对执行结果并没有影响,JMM会认为这种重排序并不非法,JMM允许这种重排序
在计算机中,软件技术和硬件技术有一个共同的目标:在不改变程序执行结果的前提下,尽可能地开发并行度