AtomicInteger:原子自增不等于整个流程原子
多个线程对普通 int 执行 ++,可能丢失更新。即便替换成 AtomicInteger,先判断再增加的业务流程也不一定安全。
问题从哪里出现
多个线程对普通 int 执行 ++,可能丢失更新。即便替换成 AtomicInteger,先判断再增加的业务流程也不一定安全。
理解核心机制
原子类把单个操作组合为不可分割的更新。getAndIncrement 与先 get 再 set 不同。涉及“检查余额后扣减”等条件更新时,需要 CAS 循环、原子更新函数或更高层同步方案。
动手做一个小实验
Java 17 或更新版本;将示例保存为 Demo.java,执行 javac Demo.java 后运行 java Demo。
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 的返回值分别用于编号生成,说明为何可能出现起始编号差一。