Java线程安全计数器首选AtomicInteger(基于CAS无锁高效),复杂逻辑用ReentrantLock,禁用volatile实现自增,高并发读多写少场景可选LongAdder。

在Java中实现线程安全的计数器,核心是避免多个线程同时读-改-写(read-modify-write)导致的竞态条件。直接用 int 或 long 配合 synchronized 虽可行,但不是最优解;现代Java更推荐使用原子类或显式锁来兼顾性能与安全性。
使用 AtomicInteger 实现高效自增
AtomicInteger 是最常用、最轻量的线程安全计数器方案。它基于CAS(Compare-and-Swap)机制,在硬件支持下实现无锁自增,性能远高于同步块。
- 调用
incrementAndGet()原子性完成“加1并返回新值” - 若需获取旧值再更新,可用
getAndIncrement() - 支持带条件的更新,如
compareAndSet(expected, updated)
示例:
AtomicInteger counter = new AtomicInteger(0);counter.incrementAndGet(); // 线程安全,无需额外同步
需要复杂逻辑时:ReentrantLock + 普通变量
当计数逻辑不止简单自增(比如“仅当小于100才加1”,或需与其他共享状态联动),原子类的单一操作难以覆盖,此时应搭配可重入锁保证临界区原子性。
立即学习“Java免费学习笔记(深入)”;
- 声明
private final ReentrantLock lock = new ReentrantLock(); - 所有读写操作前调用
lock.lock(),结束后在finally中unlock() - 比
synchronized更灵活(支持尝试获取、超时、中断响应等)
避免常见陷阱:不要用 volatile 修饰普通整型
volatile 只能保证可见性和禁止重排序,**不保证复合操作的原子性**。以下代码仍是线程不安全的:
count++; // 实际分三步:读count → 加1 → 写回,中间可能被其他线程打断
除非只做单次写入或纯读取,否则 volatile 无法解决自增问题。
高并发场景下的进阶选择:LongAdder(JDK8+)
当计数器读多写少、且写操作极其频繁(如百万级TPS监控计数),AtomicInteger 的CAS失败重试开销会升高。LongAdder 通过分段累加(cell数组)降低竞争,最终调用 sum() 合并结果。
- 写性能显著优于
AtomicLong,适合统计类场景 -
sum()不是强一致的(可能略滞后),但对监控/采样足够准确 - 初始化后直接用
increment(),语义与AtomicInteger一致










