atomicinteger 适合作为状态机的状态变量,需用 public static final int 定义互斥整型状态(如0=init、1=running),通过 compareandset 实现原子状态转换,支持单条件与多条件(循环cas)流转,并具备 volatile 内存语义。

AtomicInteger 不仅能做计数器,它天然适合做状态机的状态变量——只要状态是整型、转换逻辑简单、且每次变更只需一步判断+更新。
状态定义与取值规范
把业务状态映射为整数,例如:0=INIT、1=RUNNING、2=PAUSED、3=STOPPED。关键在于状态值必须互斥、不可重叠,避免用位运算混用多个标志(那更适合 AtomicIntegerFieldUpdater 或直接用 int + volatile + synchronized)。
推荐做法:
- 用 public static final int 常量明确定义每个状态,不依赖魔法数字
- 状态数量不宜过多(一般 ≤10),否则可读性和维护性下降
- 避免让状态值承担“版本号”或“时间戳”语义,那是 Long 类型或单独字段的事
原子状态转换的核心写法
不用 get() + if + set() 这种非原子组合,而是直接用 compareAndSet(expect, update)。
例如,只允许从 INIT → RUNNING,且不允许重复启动:
if (status.compareAndSet(INIT, RUNNING)) {
// 成功转换:执行初始化逻辑
doInitialize();
} else {
// 转换失败:说明已不是 INIT 状态,可能已被其他线程启动或终止
throw new IllegalStateException("Invalid state transition");
}
这个 if 块整体是线程安全的——compareAndSet 本身是单条 CPU 指令级原子操作,不会出现“读到 INIT,但写入前被别的线程改成 RUNNING”的竞态。
支持多条件转换与链式流转
一个状态可能允许多种前置状态,比如 STOPPED 可由 RUNNING 或 PAUSED 进入。这时不能只靠一次 compareAndSet,需循环尝试:
int current;
do {
current = status.get();
if (current == RUNNING || current == PAUSED) {
if (status.compareAndSet(current, STOPPED)) {
break; // 成功
}
} else {
throw new IllegalStateException("Cannot stop from state: " + current);
}
} while (true);
这种结构本质是 CAS 自旋,适用于转换条件不多、冲突不频繁的场景。若状态分支复杂或涉及外部 I/O,建议退回到锁保护的临界区。
注意内存可见性与延迟写入边界
compareAndSet 和 incrementAndGet 等方法自带 volatile 语义,能保证状态变更对所有线程立即可见。但若你用 lazySet 设置终态(如最后标记为 TERMINATED),要清楚它不提供“释放屏障”,其他线程可能短暂看到旧状态。
所以:
- 状态判断逻辑(如 if (status.get() == RUNNING))永远可靠,因为 get() 是 volatile 读
- 终态设置慎用 lazySet,除非你明确接受几纳秒到几微秒的可见性延迟
- 不要在 compareAndSet 后立刻依赖其他非 volatile 字段的值——它们不一定已同步










