CAS高并发性能下降的核心原因是单点热点竞争,解决思路是分散压力:LongAdder通过分段cell降低冲突,吞吐量可达AtomicInteger的3–5倍;辅以ThreadLocal批量累加、规避伪共享及接受最终一致性,实现高效计数。

CAS操作在高并发计数器中性能下降,核心原因不是“它不行”,而是单点热点竞争被放大——所有线程都在抢同一个内存地址。解决思路不是放弃CAS,而是绕开争用、分散压力、减少无效自旋。
避免单点CAS:用LongAdder替代AtomicInteger
AtomicInteger靠一个volatile变量+循环CAS更新,10万线程同时调用incrementAndGet(),99%的线程会失败重试,CPU空转飙升。LongAdder则把计数拆成多个cell(类似分段数组),线程先尝试更新自己的cell,冲突时再扩容或退到base值。压测显示:10万QPS下,LongAdder吞吐量可达AtomicInteger的3–5倍,且CPU占用更平稳。
- 默认初始化时只用base值(等价于AtomicLong)
- 发生竞争时自动创建cells数组,每个线程哈希定位到不同cell
- 最终结果 = base值 + 所有非空cell的sum,读操作略有开销但写性能跃升
控制CAS频率:批量本地累加 + 周期刷新
不追求每次请求都立刻写入全局计数器,而是让每个线程先在ThreadLocal里做本地计数,达到阈值(如100次)或定时(如10ms)再批量提交到主计数器。这样把高频CAS变成低频、粗粒度更新。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- ThreadLocal<LongAdder> localCounter = ThreadLocal.withInitial(LongAdder::new)
- 每次increment只操作localCounter.get().increment(),无竞争
- 另起守护线程或在特定时机(如请求结束前)调用globalCounter.add(localCounter.get().sumThenReset())
规避ABA与缓存行伪共享:合理设置padding和版本号
CAS本身不防ABA,但在计数场景中,数值单调递增(如QPS、请求数)天然规避了ABA问题——A→B→A不可能发生。真正影响性能的是缓存行伪共享(False Sharing):多个cell若落在同一CPU缓存行(通常64字节),彼此修改会互相使对方缓存失效。
- LongAdder内部已通过@Contended注解(JDK8+)或手动padding隔离cell字段
- 自定义CAS计数器时,确保每个原子变量独占缓存行,例如用7个long字段填充前后
- 无需为计数器引入版本号(那是AtomicStampedReference的适用场景)
权衡读写一致性:接受“最终一致”的统计语义
高并发计数器多数用于监控、限流、采样,不要求强实时精确。LongAdder的get()返回的是快照和,可能略滞后;而AtomicInteger的get()虽即时,但写入成本太高。明确业务容忍度,是优化的前提。
- 监控大盘每秒刷新一次 → 完全可用LongAdder
- 库存扣减必须精确到个位且强一致 → 不该用纯CAS计数器,应结合数据库或分布式锁
- 区分场景:统计类用LongAdder,事务类用带校验的CAS或锁机制


















