Java计数器API原子操作吗

wen java案例 2

本文目录导读:

Java计数器API原子操作吗

  1. 核心原子计数器类
  2. 关键原子方法示例
  3. 为什么说它是原子的?
  4. 对比:不使用原子的后果
  5. 性能建议

是的,Java 计数器 API(特别是 java.util.concurrent.atomic 包下的类)提供的是原子操作。

这些类通过硬件级别的原子指令(如 CAS,Compare-And-Swap 比较并交换)和 volatile 变量来实现线程安全的原子性,而无需使用重量级的 synchronized 锁。

核心原子计数器类

  • AtomicInteger:最常用的计数器。
  • AtomicLong:用于长整型计数器(当计数可能超过 20 亿时)。
  • AtomicBoolean:用于布尔状态标记。
  • LongAdder / LongAccumulator:在高并发写入场景下,性能优于 AtomicLong(通过内部分段减少竞争)。

关键原子方法示例

这些方法保证在多线程并发调用时,结果始终是正确的。

AtomicInteger counter = new AtomicInteger(0);
// 1. 原子递增:相当于 i++,但线程安全
counter.incrementAndGet(); // 返回新值 (1)
// 2. 原子递减
counter.decrementAndGet(); // 返回新值 (0)
// 3. 获取当前值(原子读)
int current = counter.get(); // 返回 0
// 4. 原子更新:预期值是 0,如果当前是 0,则更新为 10
boolean success = counter.compareAndSet(0, 10); // 成功,变为 10
// 5. 原子加法
int prev = counter.getAndAdd(5); // 返回旧值 10,新值变为 15

为什么说它是原子的?

  • 底层原理

    • 普通变量(如 int i++)在底层是“读-改-写”三步操作,线程不安全。
    • AtomicIntegerincrementAndGet() 内部调用 Unsafe.compareAndSwapInt(),这是一个硬件级别的原子指令
    • 它会在循环中尝试:如果当前值等于我读到的期望值,就更新,否则自旋重试,整个过程不会被中断。
  • 内存可见性

    • AtomicInteger 内部使用 volatile int value 存储数据。volatile 保证了所有线程能立刻看到其他线程对计数值的修改。

对比:不使用原子的后果

// 反面例子:多线程下不安全
private int count = 0;
public void unsafeIncrement() {
    count++; // 非原子操作,结果可能小于预期
}
// 正确方式:使用原子类
private AtomicInteger safeCount = new AtomicInteger(0);
public void safeIncrement() {
    safeCount.incrementAndGet(); // 原子操作,结果绝对正确
}

性能建议

  • 低/中并发AtomicInteger / AtomicLong 足够。
  • 超高并发(大量写入):使用 LongAdder,它会将计数分散到多个 Cell 中,最后需要时才汇总,减少 CAS 冲突。
    LongAdder counter = new LongAdder();
    counter.increment(); // 高并发下性能更好
    long total = counter.sum(); // 获取最终结果
特性 原子计数器 API 普通 int + synchronized
线程安全 是(但更重)
原子性 硬件级保证 锁保证
性能 高(无锁/自旋) 中(有锁,可能阻塞)
使用复杂度 中(需小心锁范围)

Java 的 AtomicIntegerAtomicLong 等计数器 API 是完全原子线程安全的,是并发编程中推荐的首选计数器实现方案。

抱歉,评论功能暂时关闭!