atomicboolean 通过 compareandset(false, true) 原子性确保初始化逻辑仅执行一次:仅首个线程成功更新状态并执行业务,其余直接跳过;不可重置,不适用于需反复启停场景。

用 AtomicBoolean 实现单次执行逻辑,核心是靠 compareAndSet(false, true) 的原子性——只有第一个线程能成功把状态从 false 改成 true,其余线程立即失败退出,从而确保某段代码只运行一次。
基本模式:CAS 检查 + 初始化动作
这是最常用也最直接的方式。初始化前声明一个静态或实例级的 AtomicBoolean,初始值为 false;在需要“只执行一次”的位置,用 compareAndSet 尝试更新,成功才执行业务逻辑:
-
声明开关:
private static final AtomicBoolean initialized = new AtomicBoolean(false); -
执行判断:
if (initialized.compareAndSet(false, true)) { /* 执行初始化 */ } -
后续调用直接跳过,因为此时值已是
true,compareAndSet(false, true)返回false
注意不可重置的语义
AtomicBoolean 本身不提供“重置为未执行”能力,一旦设为 true,就代表该逻辑已触发。如果你需要反复启用/禁用(比如开关重启),应改用其他设计,例如:
- 用两个原子变量分别表示“是否已初始化”和“当前是否启用”
- 或使用
AtomicInteger记录执行次数,配合阈值控制 - 单纯重置
set(false)会破坏“只执行一次”的契约,除非你明确接受多轮生命周期
与 volatile boolean 的关键区别
仅用 volatile boolean 无法安全实现单次逻辑,原因在于读-改-写不是原子操作:
-
if (!inited) { inited = true; doInit(); }—— 多个线程可能同时通过if判断,导致重复执行 -
AtomicBoolean.compareAndSet底层依赖 CPU 的 CAS 指令,一次完成“检查旧值+写入新值+返回结果”,无竞态窗口 - 它比加锁更轻量,且无需管理锁释放、死锁等复杂问题
适用边界与替代建议
AtomicBoolean 适合简单、无副作用、不抛异常的初始化逻辑。如果初始化函数可能 panic 或需阻塞等待完成,则它不够健壮:
- Java 中推荐用
java.util.concurrent.locks.Lock配合条件变量,或更高阶封装如CountDownLatch等协调多个线程等待 - Go 里应优先选
sync.Once,它内置阻塞等待和 panic 安全机制 - C++ 推荐
std::call_once+std::once_flag,语义更清晰、异常安全










