数据依赖性
如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性,数据依赖分3种情况:
名称 | 代码示例 | 说明 |
写后读 | A=1 B=A | 先写后读 |
写后写 | A=1 A=2 | 先写,然后再写 |
读后写 | A=B B=1 | 先读后写 |
数据依赖性的话,就比较麻烦了。上面3种情况只要修改两个操作的执行顺序,那程序执行结果就会不一样。所以,JMM和CPU不会对有数据依赖性关系的两个操作重排序的。
注意:这里的数据依赖性,仅仅针对单个处理器中执行的指令序列和单个线程中执行的操作,不同处理器之间和不同线程之间的数据依赖性不被JMM和CPU考虑。
个人见解:
JMM而言:JAVA是通过共享内存的方式来实现不同线程之间共享信息,这就意味着必须程序员来控制访问顺序(即线程/CPU之间的数据依赖性),因此JMM没必要管理线程之间的数据依赖性,这是程序员该考虑的事情。
CPU而言:由于CPU的核与核之间拥有各自独立写/读缓冲区,如果CPU使用数据依赖性的话,那就意味着读/写缓冲区必须实时刷新到内存中,那读/写缓冲区存在的意义就没了,实时刷新谁受得了。
as-if-serial语义
as-if-serial意思是:不管怎么重排序(无论是JMM还是CPU),单线程程序的执行结果不能被改变。
那又是如何实现该规则的呢?
- 单线程内存在数据依赖性的操作不做重排序。
- 单线程内不存在数据依赖性的操作进行重排序。
(想想也是,假如单线程代码编写完毕后进行运行,在不修改任何代码的情况下,运行10次得到10个不同的结果,那这门编程语言就没必要存在了,哪个傻子发明的,卧槽,CPU和虚拟机必须实现该规则)