JMM JAVA内存模型
不理解JAVA内存模型就无法深入了解JAVA的并发操作
几个问题需要阐述 1、计算机底层对并发的处理? 2、JVM对并发的处理?
操作系统并发处理方案
CPU内部工作原理简单阐述
1、CPU由运算单元(只负责计算)、数据单元(存储数据–缓存、寄存器)、控制单元(指挥做什么计算)组成; 2、控制单元获得指令,执行该指令,指令告诉运算单元从数据单元取出那几条数据进行什么计算,得到的计算结果然后在放到数据单元的哪个地方。
CPU和内存是如何配合工作的
1、CPU每次计算如果都要通过总线从内存获取数据这样速度太慢了,因此CPU数据单元中才封装了小容量的缓存和寄存器,为了提高获取数据的速度进而提高了计算速度。 2、CPU如果没有在数据单元没有获取到数据,这时候会到内存加载数据,把加载到的数据按照优先级依次放到各级缓存(L1、L2、L3三级缓存)中(TODO 待补充缓存与处理器内部对应关系)。 3、缓存行是CPU缓存的最小缓存单位(默认大小64Byte),读取数据是都是整行读取,数据不足一行时需要进行数据填充(数据填充所需要的时间比读取数据花费的时间要多),因此在程序中存储数据的时候尽量整行存储。 4、在单CPU多核或者多CPU情况下缓存之间、缓存与内存之间数据的一致性就要通过一些方法(协议–MSI/MESI/MOESI等)来解决,在L1私有L2和L3共享前提下。
缓存一致性协议的一些简单阐述(TODO 待补充)
缓存一致性协议的实现方式 –> 嗅探(Snooping) 和 目录(Directory)。
嗅探 –> 总线作为广播介质,能把请求变成全局可见即所有缓存都能同时看到总线上出现了那个请求;所有缓存都同时密切监视(嗅探)总线上出现的请求,各自独立并且正确地改变对应缓存行的状态。 目录 –> 是以点对点的数据传输,依赖于共享缓存来记录缓存行在私有缓存中的分享情况(TODO 待近一半论证)。
伪共享问题的出现与解决方案
1、出现伪共享是因为缓存行导致的 2、缓存行填充来解决伪共享问题
JAVA内存模型与JAVA运行时数据区域的阐述
JAVA运行时数据区域是Java虚拟机执行Java程序的的过程中,Java虚拟机对内存的管理(不同的内存区域存储不同的数据并且有各自的用途,以及创建和销毁的时间也不相同,有的区域随着虚拟机进程的启动而一直存在,有些区域则是依赖用户线程的启动和结束而建立和销毁)。
JAVA内存模型主要目的是定义程序中变量的访问规则,关注在虚拟机中把变量值存储到内存中和从内存中取出变量值的底层细节。也是Java虚拟机为了Java程序能正常运行而制定的一套规范,规定了JVM的数据如何与RAM的数据进行交互。 内存模型还规定了所有的变量都存储在主内存中;每个线程都有自己的工作内存,线程的工作内存中保存了被该线程使用的变量的主内存副本,线程对变量的所有操作都必须在工作内存中,线程之间的工作内存是无法直接访问的,线程之间变量值的操作都是由主内存完成的。
此处的变量是实例字段、静态字段和构成数组对象的元素。
此处的工作内存是指CPU的寄存器和高速缓存的抽象描述。
线程、主内存、工作内存的关系如下图所示:
注意:JAVA运行时数据区域与JAVA内存模型是不同层次对内存的划分!