news 2026/4/16 9:23:58

深入解析CAS写延迟:原理、优化与生产环境实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入解析CAS写延迟:原理、优化与生产环境实战


背景痛点:MESI 协议下的“隐形”写放大

第一次做高并发计数器时,我把AtomicLong当成万能药,结果 32 线程压测 QPS 只有 18 万,比单线程还低。用perf一看,大量 CPU 周期花在lock cmpxchg上,cache-miss 高达 30%。

根源是 MESI 协议:当多核同时修改同一缓存行,硬件必须串行化所有权转移。每次 CAS 成功前,其他核的对应缓存行被置为 Invalid,下一次又重新加载,形成“写放大”。如果计数器周边字段被误放在同一缓存行(False Sharing),本应是局部变量的写操作也会触发总线嗅探,延迟从 20 ns 飙到 200 ns 以上,QPS 直接腰斩。

技术对比:AtomicLong vs LongAdder vs StampedLock

下面给出 JMH 基准,场景是 1 亿次自增,线程数 1→64,测试机:Intel 8260,JDK 21。

@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.SECONDS) @State(Scope.Group) @Threads(64) public class CasLatencyCompare { private final AtomicLong al = new AtomicLong(); private final LongAdder la = new LongAdder(); private final StampedLock sl = new StampedLock(); private long v; @Benchmark @Group("atomic") public void measureAtomic() { al.incrementAndGet(); } @Benchmark @Group("adder") public void measureAdder() { la.increment(); } @Benchmark @Group("stamped") public void measureStamped() { long stamp = sl.writeLock(); try { v++; } finally { sl.unlockWrite(stamp); } } }

结果(ops/s,越高越好):

线程数AtomicLongLongAdderStampedLock
1210 M190 M180 M
835 M180 M40 M
329 M170 M15 M
645 M160 M8 M

结论:竞争强度越高,LongAdder 通过“分段”降低 CAS 频率,延迟优势越明显;StampedLock 仍逃不过同一缓存行的串行化。

核心方案

1. 缓存行填充:@Contended 实战

@jdk.internal.vm.annotation.Contended // JDK 15+ 可用,开启 -XX:-RestrictContended @ThreadSafe public final class PaddedAtomicLong { private final AtomicLong value = new AtomicLong(0); // 隐式填充 56 byte,保证独占缓存行 }

开启-XX:-RestrictContended后,perf 观察到 cache-miss 从 30% 降到 5%,32 线程 QPS 提升 2.3 倍。

2. 指数退避:降低失败重试的瞬时压力

@ThreadSafe public class BackoffCounter { private final AtomicLong counter = new AtomicLong(0); private static final int MIN_DELAY = 1; private static final int MAX_DELAY = 1024; public void increment() { int delay = MIN_DELAY; long old, neu; do { old = counter.get(); neu = old + 1; if (counter.compareAndSet(old, neu)) { return; } // 指数退避 int n = ThreadLocalRandom.current().nextInt(delay); LockSupport.parkNanos(n); delay = Math.min(delay << 1, MAX_DELAY); } while (true); } }

在高冲突场景下,退避把总线风暴从 100 万次降到 15 万次,平均延迟下降 35%。

3. 批量提交:环形缓冲区解耦

@ThreadSafe public class BatchCounter { private static final int SIZE = 1 << 14; // 16k 槽位 private final AtomicLong head = new AtomicLong(0); private final AtomicLong tail = new AtomicLong(0); @GuardedBy("head") private final long[] ring = new long[SIZE]; public void add(long delta) { long t = tail.getAndIncrement(); ring[(int) (t & (SIZE - 1))] = delta; } public long drainToSum() { long h, t; do { h = head.get(); t = tail.get(); } while (!head.compareAndSet(h, t)); long sum = 0; for (long i = h; i < t; i++) { sum += ring[(int) (i & (SIZE - 1))]; } return sum; } }

业务线程只写环形数组,无 CAS 竞争;后台单线程定时 drain,把 1 万次写合并成 1 次 CAS,延迟从 180 ns 降到 25 ns。

避坑指南

  1. 过度填充会浪费 L1 容量,反而降低命中率。建议只在“热”字段使用@Contended,并配合-XX:ContendedPaddingWidth=128调优。
  2. NUMA 机器上,CAS 延迟与节点距离正相关。把线程绑在同一 node (numactl --cpunodebind=0) 可让延迟再降 15%。
  3. 写倾斜:当业务用 CAS 做“余额扣减”,高并发下可能出现 ABA 导致透支。使用AtomicStampedReference或加版本号字段,保证“值+版本”双检。

延伸思考

当上述手段仍无法满足 99.9th 延迟 < 100 µs 的 SLA 时,是否需要引入形式化验证(如 TLA+)来证明算法正确性,而非继续调优代码?欢迎分享你在生产环境转向形式化工具的经验与踩坑。


如果你也想把“低延迟”理念落到可运行的完整项目,不妨体验下从0打造个人豆包实时通话AI动手实验:里面同样涉及环形缓冲、指数退避等并发技巧,边写代码边验证,对理解本文的优化点非常有帮助。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/8 2:49:12

构建智能客服多轮对话chatflow的工程实践:从设计到优化

背景&#xff1a;多轮对话的“三座大山” 做智能客服最怕什么&#xff1f;最怕用户说“我刚才不是已经告诉你了吗”。 &#xfffd;上下文丢失、意图漂移、槽位反复确认&#xff0c;这三座大山把多少项目卡死在上线前夜。 上下文丢失&#xff1a;HTTP无状态&#xff0c;每次请…

作者头像 李华
网站建设 2026/4/10 18:11:13

如何通过Markdown Viewer实现浏览器中的高效文档预览体验

如何通过Markdown Viewer实现浏览器中的高效文档预览体验 【免费下载链接】markdown-viewer Markdown Viewer / Browser Extension 项目地址: https://gitcode.com/gh_mirrors/ma/markdown-viewer 在日常工作学习中&#xff0c;我们经常需要查看Markdown格式的文档&…

作者头像 李华
网站建设 2026/4/1 17:43:43

视频超分辨率工具Video2X:AI驱动的视频无损放大解决方案

视频超分辨率工具Video2X&#xff1a;AI驱动的视频无损放大解决方案 【免费下载链接】video2x A lossless video/GIF/image upscaler achieved with waifu2x, Anime4K, SRMD and RealSR. Started in Hack the Valley II, 2018. 项目地址: https://gitcode.com/GitHub_Trendin…

作者头像 李华
网站建设 2026/4/11 15:14:47

解决视频下载难题的零门槛工具:无水印+断点续传 | 3步极速搞定

解决视频下载难题的零门槛工具&#xff1a;无水印断点续传 | 3步极速搞定 【免费下载链接】BiliDownload Android Bilibili视频下载器 项目地址: https://gitcode.com/gh_mirrors/bi/BiliDownload 你是否遇到过想保存B站视频却找不到简单方法的困扰&#xff1f;BiliDown…

作者头像 李华