java内存模型(7)

x33g5p2x  于2021-08-23 转载在 Java  
字(2.0k)|赞(0)|评价(0)|浏览(338)

一 说明

想要理解多线程的工作原理,单靠之前的syncronized机制的文章是不够的,本文讲述的cpu cache 模型 和 java内存模型都是抽象的概念,其有助于后续volatile关键字的学习。

二 CPU内存模型

2.1 cpu 与 内存 简介

随着现代科技的展,cpu的制造工艺已经十分发达,市场上很难见到单核的cpu,现在的cup都是至少都是2核以上,常见的2核,4核,8核,比较高级的就是16核、32核,甚至64核;可想而知单核cpu的处理效率有多么低下。虽然cpu的制造工艺已经比较发达,可是内存制造工艺方面的发展确十分有限,往往我们购买内存比常规的内存稍大的电脑其价格都是大幅度增长,其原因就是内存制造工艺受限,成本较高,现在的内存的效率很难跟上多核cpu的处理能力。受限于内存工艺的发展慢速,开始出现了使用缓存技术来提高内存的读写效率,现在的缓存最高多达3级,L1 cache最靠近cpu,随后是L2 cache,L3 cache,如下图所示,从数据中可以看出L1 cache 的容量大小较低 然后L2 cache, L3 cache容量大小依次提升。

2.2 缓存技术介绍

缓存技术就是先把我们读写的数据从内存中先提取到缓存中,在缓存中cpu对数据进行操作,cpu操作完后再将缓存中的数据刷写内存中,这样就提高了cpu对内存的读写效率(如下图所示):

2.3 缓存技术带来的问题

缓存技术明显提高了cpu的吞吐量,在多核cpu的情况下就不用对一同一个内存进行操作,每个cpu都有自己的cache,只对自己的cache进行操作;在单核的情况下缓存技术不会带来数据不一致的问题,但是在多核的情况下就会发生数据不一致问题。举个例子:当2个cpu同时对内存中的变量进行操作时,各自从内存中复制一份到自己的cache,在自己的cache中对变量进行同样的操作,然后同时刷到缓存中;在这个过程中2个cpu都对同一个变量进行了同样的操作,如果变量的值是1进行都是加1操作,那么我们应该得到的值是3,但是由于缓存不一致的问题,我们得到的结果却是2。

2.4 缓存不一致问题的解决

第一种方案:计算级按照数据传输类型来分总线有三种(数据总线,控制总线,地址总线),数据总线用于在 CPU 与内存或 IO 接口之间传送数据,控制总线用于在 CPU 与内存或 IO 接口之间传送控制信号,地址总线用于传送计算单元或 IO 接口的地址信息;基础不够的同学可以可学习一下计算级原理组成。通过总线加锁的方式解决缓存不一致的问题,即在同一时刻,只有一个cpu能拿到总线锁,对数据进行操作

第二种方案:通过缓存一致性协议来解决缓存不一致的问题,比较出名就是MESI协议;MESI协议是基于Invalidate的高速缓存一致性协议,并且是支持回写高速缓存的最常用协议之一, 它也被称为伊利诺伊州协议;MESI协议一共有4种缓存行(cpu缓存中的最小单位是缓存行(cache line))状态;

  1. 修改状态(Modify):即cache line 存在 cpu cache,对里面的数据进行了修改,随时可能写入主存中;
  2. 独享状态(exclusive):即cache line 存在 cpu cache,缓存中的数据和主存中的数据一致,如果有其他cpu从主存中读取数据,那么会变成共享状态;
  3. 共享状态(share):即这个cache line 可能被多个cpu cache 所缓存,它们之间的数据一致,当有一个cpu 对 cache 中 的 cache line 数据进行修改,那么其他cpu cache 中 cpu line 会作废;
  4. 无效状态(invalid):即 cache line 被cpu修改过;

从上面的分析可以看出,当使用MESI协议,只要cpu 对 cache 中的 cache line 进行修改操作,那么其他 cpu 中相同的 cache line 就会作废,这就保证了数据的一致性。

三 java内存模型

java线程之间的通信通过Java内存模型(JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:

  1. 共享变量存储在主存中,每个共享变量对所有线程都是可见。
  2. 每个线程都有私有的内存,即本地内存,本地内存中只存储共享变量的副本;
  3. 线程无法操作主存,线程操作完变量后,从本地内存将变量写入主存。
  4. 本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存、写缓冲区、寄存器以及其他的硬件和编译器优
    化以及硬件等


根据MESI协议的思路,Java内存模型跟其很相似;假设共享变量x存于主存中,thread1和thread2将变量x同时提取到本地内存,thread1对变量副本x进行修改操作,然后thread1将本地内存刷到主存中,thread2拥有的变量副本x就作废;基于JMM模型就保证了数据的一致性;重要的话再怎么说都不为过:JMM是抽象概念,如何保证变量的可见性是个问题

相关文章