在学习 JMM
过程中,许多和锁有关的知识点都逃不开 LOCK#
指令,比较典型的就是 volatile
了:当对 volatile
变量进行写入时,在底层的CPU级别会多生成一条 LOCK#
指令。 LOCK#
指令在多核处理器下会做两件事:
- 将当前处理器缓存行的数据**写回到系统内存**
- 无效其他CPU里该内存地址的**缓存数据**
这两件事分别涉及到了两个知识点:
- 锁总线(锁缓存)
- 缓存一致性协议
流程分析
当某个线程执行到 volatile
变量写入时(以这个点为例子),会发送一个 LOCK#
指令给执行当前线程的 CPU
(假设这个 CPU
叫 CPU0
); CPU0
首先会查看一下该数据是否在缓存行内:
- 如果该数据在缓存行,选择锁缓存(锁住对应的缓存行),然后将新的值写入缓存行以及主存中,最后无效其他
CPU
里包含该数据地址的缓存 - 如果该数据不在缓存中,就会选择锁总线(
CPU0
独占主存),完成写入后,无效化其他CPU里包含该数据地址的缓存
无效缓存是通过 缓存一致性协议 来完成的,该协议会阻止同时修改由两个以上处理器缓存的内存区域数据。
**
扩展
- 处理器使用嗅探技术保证它的内部缓存、系统内存和其他处理器的缓存的数据在总线上保持一致