研磨java内存模型(一)

前言

对于java内存模型的理解还是很有必要的,有些同学可能会想,这货不就是为了应付面试的时候背背就行了么?是有那么一点道理哈,但是我觉得搞清楚Java内存模型对于自己的深层次理解java还是很有必要的。这里我们不讲解什么java内存模型,我们来看看java内存是在什么应用场景下提出。

从物理机类比Java虚拟机

硬件的效率问题

计算机处理器处理绝大多数运行任务都不可能只靠处理器“计算”就能完成,处理器至少需要与内存交互,如读取运算数据、存储运算结果,这个 I/O 操作很难消除(无法仅靠寄存器完成所有运算任务)。由于计算机的存储设备与处理器的运算速度有几个数量级的差距,为了避免处理器等待缓慢的内存完成读写操作,现代计算机系统通过加入一层读写速度尽可能接近处理器运算速度的高速缓存。缓存作为内存和处理器之间的缓冲:将运算需要使用到的数据复制到缓存中,让运算能快速运行,当运算结束后再从缓存同步回内存之中。 

缓存一致性问题 

基于高速缓存的存储系统交互很好的解决了处理器与内存速度的矛盾,但是也为计算机系统带来更高的复杂度,因为引入了一个新问题:缓存一致性

在多处理器的系统中(或者单处理器多核的系统),每个处理器(每个核)都有自己的高速缓存,而它们有共享同一主内存(Main Memory)。当多个处理器的运算任务都涉及同一块主内存区域时,将可能导致各自的缓存数据不一致。 为此,需要各个处理器访问缓存时都遵循一些协议,在读写时要根据协议进行操作,来维护缓存的一致性。

 代码乱序执行优化问题

为了使得处理器内部的运算单元尽量被充分利用,提高运算效率,处理器可能会对输入的代码进行乱序执行。处理器会在计算之后将乱序执行的结果重组,乱序优化可以保证在单线程下该执行结果与顺序执行的结果是一致的,但不保证程序中各个语句计算的先后顺序与输入代码中的顺序一致。

乱序执行技术是处理器为提高运算速度而做出违背代码原有顺序的优化。在单核时代,处理器保证做出的优化不会导致执行结果远离预期目标,但在多核环境下却并非如此。在多核环境下, 如果存在一个核的计算任务依赖另一个核计算任务的中间结果。而且对相关数据读写没做任何防护措施,那么其顺序性并不能靠代码的先后顺序来保证,处理器最终得出的结果和我们逻辑得到的结果可能会大不相同。

以上图为例进行说明,CPU 的 core2 中的逻辑 B 依赖 core1 中的逻辑 A 先执行:

  • 正常情况下,逻辑 A 执行完之后再执行逻辑 B。

  • 在处理器乱序执行优化情况下,有可能导致 flag 提前被设置为 true,导致逻辑 B 先于逻辑 A 执行。

原创: 陈彩华

原文链接:Java内存模型原理,你真的理解吗?

猜你喜欢

转载自blog.csdn.net/qq_28165595/article/details/84995883