JMM-CPU缓存一致性协议MESI
2022-03-12 17:20:40 1 举报
JAVA代码在内存上执行过程 JMM模型的MESI协议的流程
作者其他创作
大纲/内容
调用线程
存在两个CPU同时修改变量,加锁,到底谁来加锁的问题
x=2S->I
事务串行化(Transaction Serialization)
总线会同步试图并发使用总线的事务。在一个处理器执行总线事务期间,总线会禁止其他的处理器和I/O设备执行内存的读/写。假设处理器A,B和C同时向总线发起总线事务,这时总线仲裁
refresh()
动态链接
维护
寄存器
总线锁定
不能直接修改,先去缓存行加锁,往本地写缓存行(64字节)
线程载体
x=2S
L1 cache
类加载系统ClassLoader
JMM模型
总线嗅探机制
JVM虚拟机
对任何缓存中的数据的更改都必须传播到对等缓存中的其他副本(该缓存行的副本)
Bus总线
1.jvm内置编译器
由于字节码只有JVM字节码引擎能识别,CPU与底层硬件无法识别执行,字节码需要被编译器编译成计算机硬件汇编指令
xS
方法区(元空间)
main方法栈
主内存
main()方法栈
线程0
写传播(Write Propagation)
线程
CPU缓存
S共享
缓存行
解释执行器/JIT优化
Thread 0
更新为S 共享状态,有多几个线程读这个变量,需要维护这个变量保持一致
局部变量表
丢去
线程3
E独占
内存
lock
CPU监听
修改
总线裁判通过总线上电路的高低电位来判断(CPU的时钟周期)
早期利用总线锁,保证缓存一致性,一旦使用,其他线程不允许访问内存就是Lock #
如果加锁成功,可以修改
a
缓存一致性的要求
总线裁判
工作内存
弃用协议,升级为总线锁
二进制(得有载体)
总线仲裁机制
2.硬件
线程变量池
堆区
JVM运行时数据区
程序计数器
a.class
缓存锁定
M修改
线程4
创建类对象a
CPU多级缓存结构
a.class类
x=0
变量都加载在缓存行中,争夺缓存行上Lock锁
引用缓存行
JMM-CPU
java线程栈
如果这个变量比较大,一个缓存行存不下
CPU缓存一致性协议MESI
L2 cache
保证复杂内存操作的原子性
对比各自在缓存行加锁的速度
字节码执行引擎
I无效
另个CPU操作同个变量会接收到消息,并把这个变量副本状态失效,修改状态为I
存在问题
总线锁定就是使用处理器提供的一个 LOCK#信号,当其中一个处理器在总线上输出此信号时,其它处理器的请求将被阻塞住,那么该处理器可以独占共享内存。
总线的这种工作机制可以把所有处理器对内存的访问以串行化的方式来执行。在任意时间点,最多只能有一个处理器可以访问内存。这个特性确保了单个总线事务之中的内存读/写操作具有原子性。
内存条
xE->S
本地方法栈
线程2
对单个内存位置的读/写必须被所有处理器以相同的顺序看到。理论上,一致性可以在加载/存储粒度上执行。然而,在实践中,它通常在缓存块的粒度上执行。
Lock两个缓存行不能保证原子性,只能保证锁一个缓存行的原子性
汇编指令硬件原语
独占状态,只有一个线程享有
加锁需要发消息,发消息都经过bus总线,则由总线说了算
方法出口
因为
总线锁
只有CPU调度这个线程,这个二进制才执行
缓存锁定是指内存区域如果被缓存在处理器的缓存行中,并且在Lock操作期间被锁定,那么当它执行锁操作回写到内存时,处理器不会在总线上声言LOCK#信号(总线锁定信号),而是修改内部的内存地址,并允许它的缓存一致性机制来保证操作的原子性
内核模型KLT
如果加锁失败,则不能修改
OS
Thread 1
一对一关系
Lock前缀
Lock前缀实现了类似的能力,它先对总线和缓存加锁,然后执行后面的指令,最后释放锁后会把高速缓存中的数据刷新回主内存。在Lock锁住总线的时候,其他CPU的读写请求都会被阻塞,直到锁释放保证缓存一致性,原子性
操作数栈
加锁的同时会发出本地写缓存行的消息
L3 cache
x变量共享状态,两个线程同时修改x的话,不知道听谁的
x=3S
线程1
0 条评论
下一页