本文共 1178 字,大约阅读时间需要 3 分钟。
上一篇介绍了java的内存结构,那么接下来总结java在多核多线程的环境下如何解决数据访问的复杂问题。
二、JMM与线程规范
我们知道,计算机按支持的指令大致可以分为两类:
- 精简指令集计算机(RISC),代表是如今大家熟知的 ARM 芯片,功耗低,运算能
力相对较弱。
- 复杂指令集计算机(CISC) , 代表作是Intel的X86芯片系列,比如奔腾,酷睿,至
强,以及AMD的CPU。
- CPU与缓存的结构如图
- CPU接收到指令后,它会最先向CPU中的一级缓存(L1 Cache)去寻找相关的数据,然一级缓存是与CPU同频运行的,但是由于容量较小,所以不可能每次都命中。这时CPU会继续向下一级的二级缓存(L2 Cache)寻找,同样的道理,当所需要的数据在二级缓存中也没有的话,会继续转向L3 Cache、内存(主存)和硬盘.
- Cache Line可以简单的理解为CPU Cache中的最小缓存单位。内存和高速缓存之间或高速缓存之间的数据移动不是以单个字节或甚至word完成的。相反,移动的最小数据单位称为缓存行,有时称为缓存块目前主流的CPU Cache的Cache Line大小都是64Bytes。假设我们有一个512字节的一级缓存,那么按照64B的缓存单位大小来算,这个一级缓存所能存放的缓存个数就是512/64 = 8个。
java在这样的背景下,与2014年最终修订了JSR-133规范。JMM规范明确定义了不同的线程之间,通过哪些方式,在什么时候可以看见其他线程保存到共享变量中的值;以及在必要时,如何对共享变量的访问进行同步。这样的好处是屏蔽各种硬件平台和操作系统之间的内存访问差异,实现了Java并发程序真正的跨平台。
前面提到了CPU会在合适的时机,按需要对将要进行的操作重新排序,但是有时候这个重排机会导致我们的代码跟预期不一致。怎么办呢?JMM引入了内存屏障机制。
内存屏障可分为读屏障和写屏障 ,用于控制可见性。 常见的内存屏障包括:
#LoadLoad#StoreStore#LoadStore#StoreLoad
这些屏障的主要目的,是用来短暂屏蔽CPU的指令重排序功能。和CPU约定好,看见这些指令时,就要保证这个指令前后的相应操作不会被打乱。
#StoreLoad 屏障, 能确保屏障之前执行的所有store操作,都对其他处理器可见; 在屏障后面执行的load指令, 都能取得到最新的值。换句话说, 有效阻止屏障之前的store指令,与屏障之后的load指令乱序 、即使是多核心处理器,在执行这些操作时的顺序也是一致的。
如何理解呢? 就是只要有一个CPU内核收到这类指令,就会做一些操作,同时发出一条广播, 给某个内存地址打个标记,其他CPU内核与自己的缓存交互时,就知道这个缓存不是最新的,需要从主内存重新进行加载处理。
转载地址:https://blog.csdn.net/xt00002003/article/details/115388002 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!