java内存模型原理
内存模型产生背景
在介绍java内存模型之前,我们首先要了解一下物理计算机中的并发问题,理解这些问题就可以搞清楚内存模型产生的背景
物理机中遇到的并发问题与虚拟机中的情况有不少相似之处,物理机的解决方案对虚拟机的实现有相当的参考意义.
物理机的并发问题
1、硬件的效率问题
计算机处理器处理绝大多数运行任务都不可能只靠处理器“计算”就能完成,处理器至少需要与内存交互,如读取运算数据,存储运算结果, 这个I/O过程是基本上都存在。
由于计算机的存储设备与处理器的运算速度不在一个量级上,为了避免处理器等待缓慢的内存完成读写操作,现代计算机系统通过加入一层读写速度尽可能接近处理器运算速度的高速缓存。
缓存作为内存毓处理器之间的缓冲:将运算需要使用的数据复制到缓存中,能让运算快速的运行,当运算结果结束后在从缓存同步到内存中。
2、缓存一致问题
基于高速缓存的存储系统交互很好的解决了处理器与内存速度的矛盾,但也为计算机系统带来了更高的复杂度,原因则是引发了一个新的问题:缓存一致性。
在多处理器系统中(或者多核系统中),每个处理器(每个核)都有自己的高速缓存,而他们共有同一个主内存。当多个处理器的运算任务都涉及到同一主内存区域时,将可能导致各自的缓存数据不一致。为此,需要各处理器在访问缓存时都遵守一些协议,在读写时要根据协议来进行操作,从而维护缓存的一致性。
3、代码乱序执行问题
为了使处理器内部的运算单元尽量被充分利用,提高运算效率,处理器可能会对输入的代码进行乱序执行。
处理器会在计算之后将乱序的结果重组,乱序优化可以保证在单线程下执行结果与顺序执行的结果是一致的,但不保证程序中各个语句计算的先后顺序与输入中代码的顺序是一致的。
乱序执行技术是处理器为提高运算速度而违背代码顺序的优化。在单核时代,处理器能保证在优化的前提下不会导致运算结果偏离预期目标,但是在多核条件下并非如此.
在多核环境中,如果一个核的计算任务依赖另一个核的计算任务的中间结果.而且对于相关数据的读写没有做任何防护措施,那么其执行顺序并不能靠代码的先后顺序来保证。处理器最终得出的结果和我们预期的结果会大不相同。
以上图为例说明,CPU中的core2中的逻辑B需要依赖core1中的逻辑A先执行。正常情况下,逻辑A执行完后再执行逻辑B。但是在乱序优化下可能会导致flag提前被设置为true,导致逻辑B先于逻辑A执行