CPU Cache模型与JMM

Posted privatenotesofaidanchen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CPU Cache模型与JMM相关的知识,希望对你有一定的参考价值。

1、CPU Cache模型

1.1 产生原因

在计算机中,所有的运算操作都是由CPU的寄存器完成的,CPU指令的执行过程需要涉及数据的读取和写入操作,CPU访问的所有数据都来自主存。随着技术进步,CPU的处理速度与内存的访问速度之间的差距越来越大,此时CPU直连内存的访问方式会限制CPU,降低CPU整体的吞吐量,于是就产生了缓存的设计。


1.2 模型结构

技术图片

CPU Cache的读写速度远高于内存的速度,缓解了CPU直接访问内存效率低下的问题,极大提高了CPU吞吐能力。在程序运行过程中,会将运算所需要的数据从主存复制一份到CPU Cache中,CPU进行计算时直接对Cache中的数据进行读写,当运算结束后,再将Cache中的最新数据刷新到主内存中。

技术图片

1.3 CPU缓存一致性问题

技术图片
  1 public class IncreaseTest {
  2     private static int num = 0;
  3 
  4     public synchronized static void increase() {
  5         num++;
  6     }
  7 
  8     public static int get() {
  9         return num;
 10     }
 11 
 12     public static void main(String[] args) throws InterruptedException {
 13         new Thread(() -> {
 14             for (int i = 0; i < 100000; i++) {
 15                 increase();
 16             }
 17         }).start();
 18     }
 19 }
hashCode

执行以上代码,单线程下结果为10000,但多线程下就会得到小于等于10000的结果。具体原因,在执行num++操作时,会有以下具体过程:

(1) 读取主内存的num到CPU Cache中

(2) 对num进行加一操作

(3) 将结果写回到CPU Cache中

(4) 将数据刷新到主内存中

多线程向下,每个线程都有自己的工作内存(本地内存,对应于CPU中的Cache),则变量num会在多个线程下都存在一个副本。假设现有两个线程在执行num++,都从主存中取得num=0存入CPU Cache中,线程一计算后num=1写入主存,线程二计算后也写入主存,则经过两次自增后结果仍为1,这就是缓存不一致问题。

技术图片

1.4 解决缓存不一致问题

1.4.1 总线加锁方式

技术图片

CPU和其他组件通信是通过各种总线进行的,采用总线加锁,每次只有一个CPU访问这个变量的内存,从并行退化为串行执行。即每次只有一个线程获取到num(read主存),并进行自增操作,写回主存后(write主存),完成这一过程后,下一个线程才能获取num执行操作。这种方式效率低下。


1.4.2 缓存一致性协议

其大致思想是,当CPU在操作Cache中的数据时,如果发现该变量是一个共享变量,也就是在其他CPU Cache中也存在一个副本,那么执行以下操作:

(1) 读取操作,不做任何处理,只是将Cache中的数据读取到寄存器

(2) 写入操作,发出信号通知其他CPU将该变量的Cache line置为无效状态,写入成功后,此时其他CPU通过总线嗅探机制得知写入成功,就再次从主存中获取该共享变量。

缓存一致性协议内容很复杂,以上只是大致过程。


2、Java内存模型

Java Memory Mode指定了Jav虚拟机如何与计算机的主存进行工作。Java内存模型决定了一个线程对共享变量的写入何时对其他线程可见,Java内存模型定义了线程和主存之间的抽象关系,具体如下:

(1) 共享变量存储于主存之中,每个线程都可以访问

(2) 每个线程都有私有的工作内存或者称为本地内存

(3) 工作内存只存储该线程对共享变量的副本

(4) 线程不能直接操作主内存,只有先操作了工作内存之后才能写入主内存

(5) 工作内存和Java内存模型一样也是一个抽象概念,其实并不存在,它涵盖了缓存、寄存器、编译器优化以及硬件等

技术图片

以上是关于CPU Cache模型与JMM的主要内容,如果未能解决你的问题,请参考以下文章

volatile实现原理

并发相关基础知识 - MESI - JMM

JMM模型和cpu线程模型的对八大原子操作的作用冯诺依曼计算机模型

java基础—java内存模型(JMM)CPU架构缓存一致性重排序JMM的实现JMM保证可见性有序性问题的详解

Java内存模型(JMM)总结与学习

并发编程系列之什么是Java内存模型?