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