[Q&A] 什么是CPU缓存一致性问题?
比如:多路处理器系统中, i++ 这个操作,在程序的运行过程中,首先需要将主内存中的数据复制一份存放到CPU Cache中,那么CPU寄存器在进行数值计算的时候就直接到Cache中读取和写入,当整个过程运算结束之后再将Cache中的数据刷新到主存当中。
i++在单线程
的情况下不会出现任何问题,但是在多线程
的情况下就会有问题。
每个线程都有自己的工作内存(本地内存,对应于CPU中的Cache),变量i会在多个线程的本地内存中都存在一个副本。如果同时有两个线程执行i++操作,假设i的初始值为0,每一个线程都从主内存中获取i的值存入CPU Cache中,然后经过计算再写入主内存中,很有可能i在经过了两次自增之后结果还是1,预期应该是2。这就是 典型的缓存不一致性问题。
PS:多路处理器系统,每个处理器都有自己的高速缓存,而它们又共享同一
主内存(Main Memory)
,这种系统称为共享内存多核系统(Shared Memory Multiprocessors System)
-----------------------------------------------------------------------------读书笔记摘自 书名:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)作者:周志明
缓存不一致问题的解决方法
1、通过 总线加锁
的方式
第一种方式常见于早期的CPU当中,而且是一种悲观的实现方式,从而使得只有一个CPU(抢到总线锁)能够访问这个变量的内存。这种方式效率低下,所以就有了第二种通过缓存一致性协议的方式来解决不一致的问题。
Further Reading :处理器总线的工作机制
2、通过 缓存一致性协议
的方式
在缓存一致性协议中最为出名的是Intel的 MESI
协议,MESI协议保证了每一个缓存中使用的共享变量副本都是一致的。
它的大致思想是, 当CPU在操作Cache中的数据时,如果发现该变量是一个共享变量,那么进行如下操作:
1、读取操作,不做任何处理,只是将Cache中的数据读取到寄存器。
2、写入操作,发出信号通知其他CPU将该变量的Cache line置为无效状态,其他CPU在进行该变量读取的时候不得不到主内存中再次获取。
协议是规则,光说不做,MESI就是它的一个实现
-----------------------------------------------------------------------------读书笔记摘自 书名:Java高并发编程详解:多线程与架构设计 作者:汪文君