聊聊JMM
本文转载自聊聊JMM
什么是JMM
JMM (Java Memory Model )Java内存模型是一个语言级别的内存模型抽象,它屏蔽了底层硬件实现内存一致性需求的差异,提供了对上层的统一的接口来提供保证内存一致性的编程能力。
Java作为一个跨平台的语言,Java内存模型作为一个中间层模型,它适配不同的底层硬件系统,设计一个中间层模型来屏蔽底层的硬件差异,给上层的开发者提供一个一致的使用接口,它为开发者屏蔽了底层的硬件实现细节,支持大部分的主流硬件平台。
一致性模型
任何语言编写出来的程序,最终都会转换为机器指令,按照一定的顺序去执行,所以在语言层面来讲,都是基于硬件层面提供的一致性模型基础上,来实现自身语言的功能和特性,如何保证语言层面的功能,在转换为硬件指令之后,根据语言的要求正确的运行,这就需要语言提供一种一致性模型的编程能力。Java内存模型就是java语言级别的内存模型抽象
模型一致性
模型一致性不止下面列的4种,根据概念的严格化,可以分为很多种,严格一致、顺序一致、因果一致
等,在本文中我们只列4种,这4种对我们后期理解 Java内存模型有很大的帮助
顺序一致性 Sequential Consistency
也是常说的串行语义
,它不要求全局的时钟顺序,只需要各个CPU局总的时钟顺序,
对于每个CPU来说,它看到自己程序的执行顺序始终是和程序定义是一致的,
从全局角度来看,相同的程序,在不同的CPU上运行,程序运行结果给人的感知顺序
和是符合串行语义
的,结果最终的视图是一致的
弱一致性 Weak Consistency
弱一致性是对被同步操保护的共享变量而言,系统中的某个数据被更新后,后续对该数据的读取操作可能得到更新后的值,也可能是更改前的值。它规定了只有对共享变量的同步操作完成之后,后续对该数据的读取都是更新后的值,同步操作这段时间被称为“不一致时间窗口”。
释放一致性 Release Consistency
弱一致性的粒度太大,包含了进入同步操作和释放同步操作两部分,而只有同步操作整体完成后,其他处理器才有可能保持一致性。 释放一致性规定了对同步变量的释放操作后,就对同步变量的状态广播到其他处理器,保证后续对该数据的读取都是更新后的值
进入一致性 Entry Consistency
和释放一致性一样,也是为了减小弱一致性的粒度,进入同步变量时,获取同步变量的最新状态,保证可以拿到数据更新后的最新值
再看Java内存模型
Java内存模型是一种比较松散的语言级内存模型,它通过加内存屏障(Memory Barrier),实现对共享数据的弱一致性、释放一致性、进入一致性的支持。
最终语言是以机器指令在运行,JMM适配不同硬件平台,操作硬件指令,来提供一种语言层面满足一致性模型的编程能力,使开发者不需要关心代码是以什么顺序执行,只要能够正确的使用JMM提供的同步原语,就可以保证程序最终表现出来的行为是正确的。
JMM适配了底层硬件,根据硬件指令提供一些同步原语,实现程序在多线程情况下的可见性,原子性、有序性,主要通过这些原语维护一套语言层面的运行规则 ,来保证语言层面的多线程下表现出来和串行语义一致的结果。
JMM的这种一致性模型的编程能力,使程序员不需要关运行的代码在执行时候是乱成什么顺序,以什么顺序 执行,只要能够正确的使用JMM提供的同步原语,就可以保证程序最终表现出来的行为是正确的。
主要功能就是屏蔽各硬件平台的差异,通过NATIVE方法,操作硬件指令组合,来实现JAVA中的语义,保证可见性,有序性,原子性。
- JMM提供的语义
- 使用LOCK#信号、内存屏障实现语言层面的
synchronized
语义,保证复杂指令块的原子性 ,实现对共享变量的弱一致性保证 - 对共享变量读之间插入
加载屏障
,在对共享变量写之后插入存储屏障
,来实现volatile
语义,实现对共享变量的释放一致性和进入一致性保证 - 通过
存储屏障
,禁止初始化操作不重排到构造器结束之后,来实现final
的语义
-
通过NATIVA方法屏蔽各硬件平台的差异
不同的硬件底层实现的内存屏障方式不同
不同硬件底层的硬件指令不同
-
lazy write
- 通过
存储屏障
,将写缓冲区中的数据写回主存,保证可见性和有序性 - 通过
加载屏障
,清空无效化队列,保证可见性和有序性
- 禁止重排
- 通过内存屏障,禁止指令重排,实现
as-if -serial
语义 - 锁临界区的指令不允许逸出到临界区外
- 内部锁的释放要在内部锁的申请之后执行
- 线程中的任何操作都在start方法之后执行
- 线程中的任何操作都在join方法之前执行
- 同一个volatile变量读和写之间禁止重排
结束
文章的内容原于个人的理解,有可能和实际会有偏差,如果有发现请指正,以免误导他人。
因为在JMM中大量提到了内存屏障,接下来准备写一篇关于内存屏障的文章