写缓冲器和无效队列如何优化 MESI?¶
一、MESI 的性能问题¶
MESI 协议要求写操作时: 1. 广播无效化请求。 2. 等其他核确认。 3. 才能写。
这非常慢——CPU 写一个变量要等其他核回应。
二、写缓冲器(Store Buffer)¶
CPU 不等其他核回应,先把写操作放到写缓冲器里,继续执行后续指令。
好处¶
写操作不阻塞 CPU。
问题¶
- 写缓冲器是核私有的,其他核看不到。
- 如果后续指令要读 x,得从写缓冲器里找(store forwarding)。
- 多线程下,其他核看到的 x 可能是旧值。
三、无效化队列(Invalidate Queue)¶
核 A 收到其他核的无效化请求,不立即处理,先放到无效化队列里。
好处¶
核 B 不用等核 A 真正处理完就能继续写。
问题¶
核 A 回复了"已收到",但缓存行还没真正失效,核 A 可能还在读旧值。
四、内存屏障解决¶
- StoreLoad:等写缓冲器排空,保证写对其他核可见。
- LoadLoad:让无效化队列里的请求生效,保证读到最新值。
volatile 和 synchronized 的内存屏障就是干这个的。
五、总结¶
理解
所有并发问题,本质都是"硬件为了快,偷偷优化了"。JMM 的 volatile、synchronized 就是告诉硬件"这里别优化"。