在JMM(JAVA内存模型)
中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须存在happens-before
关系。
JMM可以通过happens-before关系向程序员提供跨线程的内存可见性保证(如果A线程的写操作a与B线程的读操作b之间存在happensbefore关系,尽管a操作和b操作在不同的线程中执行,但JMM向程序员保证a操作将对b操作可见)。
如果一个操作happens-before另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前。
两个操作之间存在happens-before关系,并不意味着一定要按照happens-before原则制定的顺序来执行。如果重排序之后的执行结果与按照happens-before关系来执行的结果一致,那么这种重排序并不非法。
第一次接触该概念是在 方腾飞写的<
这条happens-before规则让人费解的地方就是happens-before规则的描述到底和谁在前边谁先执行有什么区别
<两个操作之间具有happens-before关系,并不意味着前一个操作必须要在后一个操作之前执行!happens-before仅仅要求前一个操作(执行的结果)对后一个操作可见,且前一个操作按顺序排在第二个操作之前。
这句话就是对这个问题的解释, 但也是让我最费解的一句话, 我们拆开理解:
happens-before
仅仅要求前一个操作(执行的结果)对后一个操作可见的意思是前一个操作的结果
计算完成并刷新到主内存
, 后一个操作的线程也就能看到前一个操作的执行结果
, 也就是对后一个操作可见
不意味着前一个操作必须要在后一个操作之前执行, 这句话的意思就是我们刚才说的谁在前边谁执行, 关键在于,执行这句话包含的不是一个时间点, 执行一个操作在cpu中是一个过程, 一个时间段, 一个操作必须要在后一个操作之前执行说的操作的开始,也就是这个执行时间段的开始, 总结起来这半句话的翻译就是:
不意味着前一个操作要在后一个操作之前开始执行 且前一个操作按顺序排在第二个操作之前, 这个操作顺序指的是操作的结果发生的顺序, 前一个比后一个先执行结束
总结一下这句话: happens-before不要求前一个操作和后一个操作的发生顺序, 仅仅要求前一个操作的执行完成并刷新回内存发生在后一个操作结果之前
大家应该也能猜到, 先开始的操作不一定先结束,JMM可以通过重排序等手段让代码顺序里靠后的指令先执行, 至于为什么要这样要去理解重排序的意义: 为啥要指令重排序
这个是因为JAVA内存模型有本地缓存的抽象概念, 指令执行完结果放在本地缓存其他线程是看不到的, 要刷新回主内存对其他线程才可见(大家看到内存的结果才知道这个指令执行完了) , 这要大家去看JAVA内存模型(JMM)