要让静态变量成为线程安全的计数器,关键在于控制并发修改:优先用 atomicinteger(基于cas无锁实现),或用 synchronized 保护普通 static 变量;volatile 和 static final 无法满足原子性要求。

静态变量本身不带线程安全属性,要让它成为线程安全的计数器,关键不是“加 static”,而是控制多个线程对它的并发修改。核心思路是:用原子操作替代普通++,或用同步机制保护读写过程。
用 AtomicInteger 替代 int
这是最常用、性能最好的方式。AtomicInteger 基于 CAS(比较并交换)实现无锁原子更新,天然支持多线程环境下的安全自增。
- 声明为 private static final AtomicInteger counter = new AtomicInteger(0);
- 每次计数调用 counter.incrementAndGet()(返回新值)或 counter.getAndIncrement()(返回旧值)
- 获取当前值直接用 counter.get(),重置用 counter.set(0) 或 counter.lazySet(0)
用 synchronized 保护普通 static 变量
如果必须用基本类型(如 int),或者逻辑较复杂(比如“先判断再更新”),就需要加锁保证操作的原子性。
- 推荐使用 synchronized (Counter.class) { ... },锁住类对象,避免锁粒度过大
- 也可以将方法声明为 public static synchronized void increment() { count++; }
- 注意:只包裹真正需要同步的代码段,不要把日志打印、参数校验等无关逻辑也包进去
避免常见误区
有些做法看似合理,实则无效或危险:
- volatile 不能解决 count++ 的问题——它只保证可见性,不保证原子性,两个线程仍可能同时读到 5,各自加 1 后都写回 6
- static final int 不适合做计数器——final 修饰后无法修改,只能初始化一次
- 用 this 或 new Object() 作为锁对象不行——静态方法里没有 this;new 出来的对象每个线程一个,起不到互斥作用
按场景选方案
简单计数优先用 AtomicInteger;涉及多个变量联动、条件判断或外部资源访问时,才考虑 synchronized 或 ReentrantLock。
- 单次增减、获取、重置 → AtomicInteger
- “如果未初始化就创建”、“更新 A 同时更新 B” → 加锁
- 纯读操作(如只 get)→ 无需同步,AtomicInteger 的 get() 本身就是线程安全的
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











