Java内存模型 上

Java内存模型(Java Memory Model,JMM)

内存模型规定:

  1. 所有的变量都是存在主存当中(类似于物理内存)
  2. 每个线程都有自己的工作内存(类似于高速缓存)
  3. 线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作。
  4. 每个线程不能访问其他线程的工作内存。

缓存一致性(Cache coherence)问题

当程序在运行过程中,会将运算需要的数据从主存复制一份到CPU的高速缓存当中,那么CPU进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据,当运算结束之后,再将高速缓存中的数据刷新到主存当中

在一个系统中,当许多不同的设备共享一个共同存储器资源,在高速缓存中的数据不一致,就会产生问题。也就是说如果一个变量在多个CPU中都存在缓存(一般在多线程编程时才会出现),那么就可能存在缓存不一致的问题。

缓存一致性可以分为三个层级:

  • 在进行每个写入运算时都立刻采取措施保证数据一致性
  • 每个独立的运算,假如它造成数据值的改变,所有进程都可以看到一致的改变结果
  • 在每次运算之后,不同的进程可能会看到不同的值(这也就是没有一致性的行为)

为了解决缓存不一致性问题,通常来说有以下2种解决方法:

  1. 通过在总线加LOCK锁的方式

  2. 通过缓存一致性协议

最出名的就是Intel 的MESI协议,MESI协议保证了每个缓存中使用的共享变量的副本是一致的

它核心的思想是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取。

##参考资料