在学习 JMM 过程中,许多和锁有关的知识点都逃不开 LOCK# 指令,比较典型的就是 volatile 了:当对 volatile 变量进行写入时,在底层的CPU级别会多生成一条 LOCK# 指令。 LOCK# 指令在多核处理器下会做两件事:

  1. 将当前处理器缓存行的数据**写回到系统内存**
  2. 无效其他CPU里该内存地址的**缓存数据**

这两件事分别涉及到了两个知识点:

  1. 锁总线(锁缓存)
  2. 缓存一致性协议

流程分析

当某个线程执行到 volatile 变量写入时(以这个点为例子),会发送一个 LOCK# 指令给执行当前线程的 CPU (假设这个 CPUCPU0 ); CPU0 首先会查看一下该数据是否在缓存行内:

  • 如果该数据在缓存行,选择锁缓存(锁住对应的缓存行),然后将新的值写入缓存行以及主存中,最后无效其他 CPU包含该数据地址的缓存
  • 如果该数据不在缓存中,就会选择锁总线( CPU0 独占主存),完成写入后,无效化其他CPU里包含该数据地址的缓存

无效缓存是通过 缓存一致性协议 来完成的,该协议会阻止同时修改由两个以上处理器缓存的内存区域数据。
**

扩展

  • 处理器使用嗅探技术保证它的内部缓存、系统内存和其他处理器的缓存的数据在总线上保持一致