JMM内存模型
序
since:2019年9月2日 9:11
auth: Hadi
update: 2021年5月16日 22:36
参考:
https://blog.csdn.net/lxm55913153/article/details/79208126
JMM
Java内存模型 Java Memort Model 简称为JMM。
JMM定义了java虚拟机在内存中的工作方式,是一种逻辑性的结构。
JMM定义了多线程之间共享变量的可见性以及如果在需要的时候对共享变量进行同步。
JMM操作类型
JMM为了进行数据的共享,对变量的操作分为以下8类:
- read
从主内存中读取数据。 - load
将主内存中的数据写入工作内存中(某子线程) - use
从工作内存中读取数据来计算 - assign
将计算好的值重新写入工作内存中 - store
将工作内存的数据写回主内存 - write
将store写入的变量赋值给主内存中的变量位置 - lock
将主内存变量进行加锁,标识该变量被线程独占状态 - unlock
将主内存变量进行解锁,解锁后其他线程可以锁定该变量
具体流程可以参考下面流程图:
PS:红色方框中的操作也是在主内存中的进行的。
主内存 main memory,本地内存 local memory
local memory并不真实存在,只是抽象概念,涵盖缓存,写缓冲区,寄存器以及其他硬件和编译器优化等。
竞争现象和总线加锁
竞争现象
如果多个线程共享了一个对象,且多个线程在同时修改这个对象,那么就会产生竞争的现象。如下图:
两个线程同时对一个变量进行++的操作,那么可能会导致取数时为1,写回主内存的时候都写为1,导致丢失一次add操作。
总线枷锁
对上述情况的发生,我们可以操作lock的操作,就是会导致性能太低,无法高效。
Cpu从主内存读取数据到高速缓存,会在总线对这个数据加锁,
这样其它Cpu没法去读或写这个数据,直到这个Cpu使用完数据放锁之后其它Cpu才能读取该数据
MESI缓存一致性协议
多个Cpu从主内存读取同一个数据到各自的高速缓存,当其中某个Cpu修改了缓存里的数据,该数据会马上同步回主内存,其它Cpu通过总线嗅探机制可以感知到数据的变化从而将自己缓存里的数据失效,并进行数据的重新read、load。
Volatile缓存可见性实现原理
底层实现主要是通过汇编lock前缀指令,它会锁定这块内存区域的缓存(缓存行锁定)并回写到主内存。
在IA-32架构软件开发者手册对lock指令的解释:
- 会将当前处理器缓存行的数据立即写回到系统内存。
- 这个写回内存的操作会引起在其他CPU里缓存了该内存地址的数据无效(MESI协议)
Java程序汇编代码查看
-server -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:CompileCommand=compileonly,*VolatileVisibilityTest,prepareData