知识卡片
自旋怕总线风暴
内容
CAS 自旋在低竞争下很快,但 SMP 架构中所有核心共享同一条总线连接主存。X86 的 CAS 指令是 lock cmpxchg,与 volatile 一样带 lock 前缀,会让其他核缓存该地址的数据失效。许多线程同时反复 CAS 同一变量,会触发大量缓存失效和核间总线通信,流量过大就成瓶颈,即总线风暴。JUC 基于 CAS 的锁用队列给线程排队而非人人都 CAS,正是为了减少这个开销。
参考来源
- 位置:《Java高并发核心编程.卷2,多线程、锁、JMM、JUC、高并发设计模式》第5章《JUC显式锁的原理与实战》5.2.5节《CAS可能导致"总线风暴"》(源文件:_epub-src/OEBPS/Text/chapter166.xhtml)
- 结论依据:原文说明SMP架构CPU的所有核共享一条总线连接主存,CAS对应的lock cmpxchg指令与volatile一样会产生"缓存一致性流量";当很多线程同时执行lock前缀指令,“在SMP架构的CPU平台上必然会导致总线风暴”,并给出JUC用队列排队抢锁以减少CAS数量的解决思路,因此推出本卡结论。
- 原始内容:由于使用lock前缀指令的Java操作(包括CAS、volatile)恰恰会产生缓存一致性流量,当有很多线程同时执行lock前缀指令操作时,在SMP架构的CPU平台上必然会导致总线风暴……JUC基于CAS实现的轻量级锁如何避免总线风暴呢?答案是:使用队列对抢锁线程进行排队,最大程度上减少了CAS操作数量。