一、计算机内存与JVM内存简析
- 计算机内存:
计算机CPU(central processing unit)和内存的交互是最频繁的,内存是我们的高速缓存区。用户磁盘和CPU的交互,而CPU运转速度越来越快,磁盘远远跟不上CPU的读写速度,才设计了内存,用户缓存用户IO等待导致CPU的等待成本。但是随着CPU的发展,内存的读写速度也远远跟不上CPU的读写速度,因此,为了解决这一纠纷,CPU厂商在每颗CPU上加入了高速缓存,用来缓解这种症状。因此CPU与内存的交互如下图:
同样,我们知道单核CPU的主频不可能无限增长,想要提升性能,需要多个处理器协同工作,Intel总裁贝瑞特单膝下跪事件标识着多核时代的到来。
基于高速缓存的存储交互很好的解决了处理器与内存之间的矛盾,也引入了新的问题:缓存一致性问题。在多处理器系统中,每个处理器有自己的高速缓存,而他们又共享同一块内存(主存),当多个处理器运算都涉及到同一块内存区域的时候,就有可能出现缓存不一致的问题。为了解决这一问题,需要各个处理器运行时都遵守一些协议,在运行时将需要这些协议保存数据的一致性。协议包括:MSI/MESI/MOSI/Synapse/Firely/DragonProtocol等,如下图:
简述下图的总线锁机制,CPU和其他部件通信是通过总线进行,如果在总线加LOCK锁的话,也就是阻塞了其他CPU对其他部件的访问(如内存),从而使得只能有一个CPU能使用这个变量的内存
由于在锁住总线期间,其他CPU无法访问内存,导致效率低下。
所以就出现了缓存一致性协议。最出名的就是Intel 的MESI协议,MESI协议保证了每个缓存中使用的共享变量的副本是一致的。它核心的思想是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取。
- JVM内存:
Java虚拟机内存模型中定义的访问操作和物理计算机处理的基本一直,如图:
JAVA中通过多线程机制使得多个任务同时执行处理,所有的线程共享JVM内存区域主存,而每一个线程又单独有自己的工作内存,当线程与内存区域进行交互时,数据从主存拷贝到工作内存,进而交由线程处理(操作码+操作数)
为了或得较好的执行性能,JAVA内存模型并没有限制执行引擎使用处理器的寄存器或者高速缓存来提升指令执行速度,也没有限制编译器对指令进行重排序。
也就是说,在JAVA内存模型中,也会存在缓存一致性问题和指令重排序问题