Administrator
Published on 2026-06-02 / 0 Visits
0

AtomicInteger 是什么怎么用

#AI

一、AtomicInteger 是什么

AtomicIntegerjava.util.concurrent.atomic 包提供的线程安全整型工具类,基于 CAS(Compare-And-Swap)+ volatile + 自旋实现无锁原子操作,用来在多线程下安全更新单个 int 值,性能远好于 synchronized

  • 类继承:AtomicInteger extends Number implements Serializable
  • 诞生:JDK 1.5+
  • 定位:无锁、非阻塞、轻量级并发工具

二、为什么需要 AtomicInteger

普通 int i++ 不是原子操作,实际分三步:

  1. 读取 i
  2. 计算 i+1
  3. 写回 i

多线程下会丢失更新(竞态条件)。传统用 synchronizedLock,但:

  • synchronized阻塞、上下文切换、性能差
  • Lock:编码复杂,仍有阻塞

AtomicInteger无锁 CAS 自旋,线程不阻塞,只重试,高并发下吞吐更高


三、核心结构(底层字段)

public class AtomicInteger extends Number implements Serializable {
    // 核心值:volatile 保证可见性与禁止指令重排
    private volatile int value;

    // Unsafe:直接操作内存、执行 CAS 原语
    private static final Unsafe unsafe = Unsafe.getUnsafe();

    // value 字段在对象内的内存偏移地址
    private static final long valueOffset;

    static {
        try {
            // 初始化 valueOffset
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
}
  • volatile int value:保证多线程立即可见、禁止重排
  • Unsafe + valueOffset:直接操作内存,调用 CPU CAS 指令

四、常用 API(原子操作)

1. 构造器

AtomicInteger()          // 初始值 0
AtomicInteger(int init)  // 指定初始值

2. 基础读写

  • get():获取当前值
  • set(int newValue):强制设值(volatile 写)
  • lazySet(int newValue):延迟写(不保证立即可见,性能更高)

3. 自增/自减(最常用)

方法作用示例(初值5)
getAndIncrement()返回旧值,再+15→返回5
incrementAndGet()先+1,返回新值5→返回6
getAndDecrement()返回旧值,再-15→返回5
decrementAndGet()先-1,返回新值5→返回4
AtomicInteger cnt = new AtomicInteger(0);
cnt.incrementAndGet(); // 原子 +1,返回新值

4. 加减与更新

  • addAndGet(int delta):加 delta,返回新值
  • getAndAdd(int delta):返回旧值,再加 delta
  • updateAndGet(IntUnaryOperator):函数式更新(JDK8+)
  • getAndUpdate(IntUnaryOperator):函数式更新,返回旧值

5. CAS 核心方法

// 如果当前值 == expect,就更新为 update,返回 true;否则 false
boolean compareAndSet(int expect, int update)
  • 乐观锁核心:无锁、非阻塞、失败重试

五、底层原理:CAS + 自旋

getAndIncrement() 为例(JDK 源码简化):

public final int getAndIncrement() {
    int prev, next;
    do {
        prev = get();          // 1. 读当前值
        next = prev + 1;       // 2. 计算新值
    // 3. CAS:prev 没变才更新,失败就自旋重试
    } while (!compareAndSet(prev, next));
    return prev;
}
  • CAS 原语unsafe.compareAndSwapInt(...)CPU 指令级原子
  • 自旋重试:失败不阻塞,循环直到成功,高并发下效率远高于锁

六、典型使用场景

  1. 计数器(点赞数、访问量、ID 生成)
private static final AtomicInteger seq = new AtomicInteger(0);
public static int nextId() {
    return seq.incrementAndGet();
}
  1. 并发状态标记
AtomicInteger status = new AtomicInteger(0);
if (status.compareAndSet(0, 1)) {
    // 成功抢占,执行任务
}
  1. 无锁队列/栈的索引维护

七、优缺点与注意事项

优点

  • 无锁、非阻塞:线程不挂起,上下文切换少
  • 高性能:高并发下比 synchronized 快很多
  • 轻量:仅包装 int,无额外对象开销

缺点

  • 自旋消耗 CPU:竞争激烈时,空转浪费 CPU
  • ABA 问题:值从 A→B→A,CAS 误判未变
    • 解决:用 AtomicStampedReference(带版本号)
  • 只能保证单个变量原子:复合操作仍需锁

对比

  • 低竞争:AtomicIntegersynchronized
  • 高竞争:AtomicInteger 显著优于 synchronized
  • 超高并发(如 10w+/s):用 LongAdder(分段锁,CAS 更少)

八、总结

  • AtomicInteger = 原子 + int无锁、线程安全、高性能
  • 核心:CAS + volatile + 自旋,依赖 Unsafe 直接操作内存
  • 适用:计数器、状态位、ID 生成等单变量原子场景
  • 替代:优先 AtomicInteger;超高并发用 LongAdder;需版本控制用 AtomicStampedReference