Java中包装类(如Integer)不可用于多线程并发计数,因其不可变且无原子操作;应使用AtomicInteger、AtomicLong或LongAdder等原子类实现线程安全的高效计数。

Java 中包装类本身不能用于多线程并发计数——这是个常见误解。
Integer、Long 等包装类是不可变的,不是线程安全的“计数器”,它们不提供原子更新能力。用 Integer count = 0; count++ 在多线程下会丢失更新,根本起不到计数作用。
真正安全的做法是:不用包装类做并发计数,改用原子类或同步机制。
✅ 正确方案:用原子类替代包装类
AtomicInteger、AtomicLong 是专为并发计数设计的,底层基于 CAS,无锁且高效:
private static final AtomicInteger counter = new AtomicInteger(0);
public static void increment() {
counter.incrementAndGet(); // 原子自增,线程安全
}
public static int getValue() {
return counter.get(); // 安全读取
}- 不依赖
synchronized,避免串行阻塞 - 比
synchronized (lock) { count++; }吞吐量更高(尤其读多写少场景) - 支持
compareAndSet、addAndGet、getAndUpdate等丰富原子操作
⚠️ 注意:不要把 AtomicInteger 当作 Integer 的“线程安全版”来随意赋值或传递——它本身可变,但操作必须用其原子方法,而非 i = i + 1 这类非原子表达式。
❌ 错误做法:试图用包装类“凑合”
以下写法全部不安全,会导致竞态条件:
立即学习“Java免费学习笔记(深入)”;
// 错!Integer 不可变,+1 返回新对象,原引用未同步 Integer count = 0; count = count + 1; // 多线程下等价于 count = Integer.valueOf(count.intValue() + 1),中间值丢失 // 错!自动装箱 + 非原子读-改-写 List<Integer> list = Collections.synchronizedList(new ArrayList<>()); list.add(1); // 单个 add 安全,但 list.size()++ 不安全
原因很直接:
-
count + 1是三步:读count→ 解包 → 加 1 → 装箱 → 赋值给count - 多线程可能同时读到旧值,各自加 1 后都写回,结果只 +1 而非 +2
? 替代方案对比(按推荐顺序)
| 方案 | 是否适合高频并发计数 | 说明 |
|---|---|---|
AtomicInteger / AtomicLong
|
✅ 强烈推荐 | 无锁、低开销、API 清晰,JDK 自带 |
synchronized 块 + 基本类型(如 int) |
⚠️ 可用,但性能较低 | 适合逻辑复杂、需多步协调的计数,避免过度竞争即可 |
LongAdder(高并发累加场景) |
✅ 更优(比 AtomicInteger) | 内部分段计数,极端高并发(如百万 TPS)下吞吐更高,最终用 sum() 获取总和 |
包装类(Integer) |
❌ 绝对不可用 | 不可变 ≠ 线程安全;它连“修改”都不支持,更谈不上原子计数 |
? 小贴士:别混淆“不可变”和“可安全计数”
-
String不可变 → 适合当 key 或参数传入多线程,防污染 -
AtomicInteger可变 → 专门设计为可安全更新,内部状态受 CAS 保护 -
Integer不可变 + 无原子方法 → 既不能改,也不能安全地“算着改”,纯属“只读数字容器”
所以,多线程计数这件事,包装类不是解决方案,而是干扰项。绕过它,直奔 AtomicInteger 或 LongAdder 就对了。


















