JAVA 缓存一致性协议

当有多个CPU要访问同一个内存空间时,该内存的值会在每个CPU的缓存中有一个拷贝,如何同步这些拷贝呢?

1.互联线的概念

互连线是处理器于主存以及处理器与处理器之间进行通信的媒介,有两种基本的互联结构:SMP(symmetric multiprocessing 对称多处理)和NUMA(nonuniform memory access 非一致内存访问)

JAVA 缓存一致性协议

SMP系统结构非常普通,因为它们最容易构建,很多小型服务器采用这种结构。处理器和存储器之间采用总线互联,处理器和存储器都有负责发送和监听总线广播的信息的总线控制单元。但是同一时刻只能有一个处理器(或存储控制器)在总线上广播,所有的处理器都可以监听。
很容易看出,对总线的使用是SMP结构的瓶颈。

NUMP系统结构中,一系列节点通过点对点网络互联,像一个小型互联网,每个节点包含一个或多个处理器和一个本地存储器。一个节点的本地存储对于其他节点是可见的,所有节点的本地存储一起形成了一个可以被所有处理器共享的全局存储器。可以看出,NUMP的本地存储是共享的,而不是私有的,这点和SMP是不同的。NUMP的问题是网络比总线复制,需要更加复杂的协议,处理器访问自己节点的存储器速度快于访问其他节点的存储器。NUMP的扩展性很好,所以目前很多大中型的服务器在采用NUMP结构。

对于上层程序员来说,最需要理解的是互连线是一种重要的资源,使用的好坏会直接影响程序的执行性能。

缓存一致性协议 主要就是处理多个处理器处理同一个主存地址的问题。

MESI是一种主流的缓存一致性协议,已经用在Pentium和PowerPC处理器中。它定义了缓存块的几种状态

  1. modified(修改):缓存块已经被修改,必须被写回主存,其他处理器不能再缓存这个块
  2. exclusive(互斥):缓存块还没有被修改,且其他处理器不能装入这个缓存块
  3. share(共享):缓存块未被修改,且其他处理器可以装入这个缓存块
  4. invalid(无效):缓存块中的数据无效

JAVA 缓存一致性协议

缓存一致性协议存在的一个最大的问题是可能引起缓存一致性流量风暴,之前我们看到总线在同一时刻只能被一个处理器使用,当有大量缓存被修改,或者同一个缓存块一直被修改时,会产生大量的缓存一致性流量,从而占用总线,影响了其他正常的读写请求。

一个最常见的例子就是如果多个线程对同一个变量一直使用CAS操作,那么会有大量修改操作,从而产生大量的缓存一致性流量,因为每一次CAS操作都会发出广播通知其他处理器,从而影响程序的性能。

CPU写到高速缓存的值何时写回到主内?如果是多个计算芯片在处理同一个内存地址,那么如何处理这个时间差是个问题。

通常使用内存屏障的方法