深入理解AtomicBoolean的使用与底层原理
概念
AtomicBoolean是java.uti.concurrent.atomic中的一个原子类,用于在多线程环境下安全的操作布尔值。
1、核心特性
- 提供了无锁的线程安全操作
- 使用了CAS(Compare-And-Swap)操作保证原子性
- 避免了使用Synchronized关键字的性能开销
2、原子操作
所有的操作都是原子性的,不会被其他线程中断:
AtomicBoolean flag = new AtomicBoolean(false);
flag.set(true); // 原子设置
boolean value = flag.get(); // 原子读取
主要方法
基本使用
// 构造函数
AtomicBoolean flag1 = new AtomicBoolean(); // 默认为false
AtomicBoolean flag2 = new AtomicBoolean(true); // 初始值为true// 基本读写
flag.set(true); // 设置值
boolean value = flag.get(); // 获取值
原子更新原理
// getAndSet - 设置新值并返回旧值
boolean oldValue = flag.getAndSet(true);// compareAndSet - CAS操作
boolean success = flag.compareAndSet(false, true); // 如果当前值是false,则设置为true// weakCompareAndSet - 弱CAS操作(可能会意外失败)
boolean success = flag.weakCompareAndSet(false, true);
实际场景使用
1、状态标志控制
public class TaskManager {private final AtomicBoolean isRunning = new AtomicBoolean(false);public void startTask() {if (isRunning.compareAndSet(false, true)) {// 只有状态从false切换成true时才启动任务executeTask();}}public void stopTask() {isRunning.set(false);}
}
2、一次性初始化问题
确保只初始化一次,只有第一次false转换成true时才执行逻辑
public class LazyInitializer {private final AtomicBoolean initialized = new AtomicBoolean(false);private volatile Object resource;public Object getResource() {if (initialized.compareAndSet(false, true)) {// 确保只初始化一次,只有第一次false转换成true时才执行逻辑resource = createExpensiveResource();}return resource;}
}
3、线程间通信
AtomicBoolean isEnd = new AtomicBoolean(false);executorService.execute(new Runnable() {
@Override
public void run() {try {startJob();} catch (Exception e) {logger.error(e.message);} finally {isEnd.set(true); //任务执行完成修改标志位}
}
});while(!isEnd.get()) { //在任务执行结束之前try {otherJob(); //执行其他任务Thread.sleep(5000);} catch (InterruptedException e) {Thread.currentThread().interrupt();break;}
}性能优势
// 使用 synchronized(性能较低)
private boolean flag = false;
public synchronized void setFlag(boolean value) {this.flag = value;
}
public synchronized boolean getFlag() {return this.flag;
}// 使用 AtomicBoolean(性能更好)
private final AtomicBoolean flag = new AtomicBoolean(false);
public void setFlag(boolean value) {flag.set(value);
}
public boolean getFlag() {return flag.get();
}
总结:
程序中使用的优势:,
- 线程安全:异步线程设置 atomicBooleanFlag.set(true),主线程读取 atomicBooleanFlag.set(get) 都是线程安全的
- 可见性:一个线程的修改对其他线程立即可见
- 性能:比使用 Synchronized性能更好
- 简单性:代码简洁,逻辑清晰
注意事项
- 适用场景:适合简单的布尔状态控制,复杂逻辑仍需要其他同步机制
- 内存开销:相比普通
boolean,AtomicBoolean有额外的内存开销 - CAS特性:了解CAS操作的特点,在高竞争环境下可能需要重试
