AtomicBoolean + CAS 机制通俗讲解 什么是 CASCASCompare And Swap比较并交换是一种原子操作就像是一个智能开关。生活中的比喻想象一个厕所门上的有人/无人指示牌传统方式有问题 1. 你看了一眼牌子无人 2. 你准备去改牌子 3. 这时另一个人也看到无人也准备改牌子 4. 你们都改了牌子 → 两个人都进去了❌ CAS 方式安全 1. 你看了一眼牌子无人 2. 你对牌子说如果现在是无人就帮我改成有人 3. 牌子会检查如果确实还是无人就改成有人返回成功 ✅ 4. 如果已经被别人改成了有人就返回失败 ❌Java 中的 AtomicBooleanAtomicBoolean就是一个线程安全的布尔值它提供了 CAS 操作。核心方法compareAndSetAtomicBooleanflagnewAtomicBoolean(false);// 尝试将 false 改成 truebooleansuccessflag.compareAndSet(false,true);if(success){System.out.println(成功获取执行权);}else{System.out.println(已经有任务在运行了本次跳过);}compareAndSet 的工作原理publicbooleancompareAndSet(booleanexpect,booleanupdate){// 伪代码逻辑// 1. 读取当前值// 2. 如果当前值 expect期望值// 3. 则将当前值设置为 update新值返回 true// 4. 否则返回 false// 整个过程是原子的不会被其他线程打断}实际应用场景场景1防止重复执行publicclassTaskExecutor{privatefinalAtomicBooleanisRunningnewAtomicBoolean(false);publicvoidexecute(){// 尝试获取执行权if(!isRunning.compareAndSet(false,true)){System.out.println(任务正在执行中跳过本次请求);return;}try{// 执行业务逻辑doWork();}finally{// 释放执行权isRunning.set(false);}}}执行流程时刻1: 线程A调用 execute() compareAndSet(false, true) → 成功isRunning true 开始执行任务... 时刻2: 线程B调用 execute() compareAndSet(false, true) → 失败当前是true 直接返回不执行任务 时刻3: 线程A执行完毕 finally 块中 isRunning.set(false) 时刻4: 线程C调用 execute() compareAndSet(false, true) → 成功isRunning true 开始执行任务...场景2单次初始化publicclassSingleton{privatestaticfinalAtomicBooleaninitializednewAtomicBoolean(false);publicvoidinit(){// 只有第一个调用的线程能成功if(!initialized.compareAndSet(false,true)){return;// 已经初始化过了}// 执行初始化逻辑doInit();}}CAS vs synchronized特性CAS (AtomicBoolean)synchronized实现方式硬件级别的原子指令JVM 层面的锁机制性能无锁竞争时更快有锁的开销阻塞非阻塞立即返回可能阻塞等待适用场景简单的状态切换复杂的同步逻辑代码复杂度简单相对复杂优缺点分析优点 ✅轻量级不需要创建锁对象非阻塞不会让线程进入 WAITING 状态简洁一行代码完成检查和设置高效在低竞争场景下性能更好缺点 ❌需要手动管理状态必须在 finally 中重置标志容易忘记释放如果忘记set(false)后续所有请求都会被拒绝不支持重入同一个线程不能多次获取ABA 问题虽然 Boolean 类型不存在这个问题完整示例importjava.util.concurrent.atomic.AtomicBoolean;publicclassSingleTaskRunner{privatefinalAtomicBooleanisRunningnewAtomicBoolean(false);/** * 执行任务如果已有任务在执行则跳过 */publicvoidrun(Runnabletask){// CAS 尝试获取执行权if(!isRunning.compareAndSet(false,true)){System.out.println(⚠️ 任务正在执行中本次请求被跳过);return;}System.out.println(✅ 获取执行权开始执行任务);try{task.run();System.out.println(✅ 任务执行成功);}catch(Exceptione){System.err.println(❌ 任务执行异常: e.getMessage());}finally{// ⚠️ 重要必须释放执行权isRunning.set(false);System.out.println( 释放执行权);}}// 测试publicstaticvoidmain(String[]args)throwsInterruptedException{SingleTaskRunnerrunnernewSingleTaskRunner();// 第一次调用成功执行runner.run(()-{System.out.println(任务1 执行中...);try{Thread.sleep(2000);}catch(InterruptedExceptione){}System.out.println(任务1 执行完毕);});// 立即第二次调用会被跳过runner.run(()-{System.out.println(任务2 执行中...);});// 等待2秒后第三次调用可以执行Thread.sleep(2500);runner.run(()-{System.out.println(任务3 执行中...);});}}输出✅ 获取执行权开始执行任务 任务1 执行中... ⚠️ 任务正在执行中本次请求被跳过 任务1 执行完毕 释放执行权 ✅ 获取执行权开始执行任务 任务3 执行中... 释放执行权总结CAS是一种乐观的原子操作先假设能成功如果不成功就放弃AtomicBoolean提供了线程安全的布尔值操作compareAndSet是核心方法如果当前值符合预期就更新并返回 true适合用于简单的状态标记和防重复执行场景记得在finally块中释放状态避免死锁