WMX · 随记
·Java· 3 分钟阅读

AtomicInteger:原子自增不等于整个流程原子

多个线程对普通 int 执行 ++,可能丢失更新。即便替换成 AtomicInteger,先判断再增加的业务流程也不一定安全。

Java 系列概览:类型与值、状态与资源、边界验证
Java 系列概览:类型与值、状态与资源、边界验证 点击图片查看大图 ↗

问题从哪里出现

多个线程对普通 int 执行 ++,可能丢失更新。即便替换成 AtomicInteger,先判断再增加的业务流程也不一定安全。

理解核心机制

原子类把单个操作组合为不可分割的更新。getAndIncrement 与先 get 再 set 不同。涉及“检查余额后扣减”等条件更新时,需要 CAS 循环、原子更新函数或更高层同步方案。

动手做一个小实验

Java 17 或更新版本;将示例保存为 Demo.java,执行 javac Demo.java 后运行 java Demo。

Java11 行 · 可横向滚动
import java.util.concurrent.atomic.AtomicInteger;
public class Demo {
    public static void main(String[] args) {
        var count = new AtomicInteger(0);
        int before = count.getAndIncrement();
        int after = count.incrementAndGet();
        System.out.println(before + "," + after);
        count.updateAndGet(value -> Math.min(value + 1, 10));
        System.out.println(count.get());
    }
}

适用边界与常见误区

更新函数在竞争下可能执行多次,不能放外部副作用。原子计数也不能自动保证多个字段之间的一致性。

继续练习

把 getAndIncrement 与 incrementAndGet 的返回值分别用于编号生成,说明为何可能出现起始编号差一。

参考资料

阅读相关官方文档或原始资料 ↗

← 返回文章归档