AtomicBoolean能否替代volatile boolean实现双重检查锁定逻辑?
问题1:volatile boolean替换为AtomicBoolean是否等效、性能差异是否可忽略
- 两者在原有DCL逻辑下可以达到完全相同的线程安全效果:
AtomicBoolean内部封装的value属性本身就是volatile修饰的,get()、set()方法的可见性、指令重排序约束和直接操作volatile boolean变量完全一致。只要你把原代码里的变量读写对应改成isInitialised.get()和isInitialised.set(true),逻辑和原来的DCL没有任何区别。 - 性能差异在绝大多数业务场景下可以忽略:
两者的读操作都是直接读volatile变量,延迟几乎无差别;写操作也都是volatile写,只有在百万级以上超高并发频繁写的极端场景下才会出现可感知的差异,普通业务场景完全不需要考虑这个性能开销。
问题2:仅用CAS替换整个DCL逻辑是否等效
不能实现相同效果,存在严重的线程安全问题,核心漏洞有两个:
- 初始化操作的可见性没有保障:当第一个线程CAS成功进入初始化逻辑时,后续线程调用
compareAndSet会直接返回false,跳过初始化流程,但此时第一个线程的初始化逻辑还没有执行完成,后续线程会直接拿到未初始化完成的资源,导致业务错误。而原DCL的synchronized块可以保证,后续进入同步块的线程一定能看到前一个线程初始化完成的所有结果。 - 初始化失败无法重试:如果第一个线程执行初始化逻辑的过程中抛出异常,
AtomicBoolean的值已经被CAS改成了true,后续所有线程都会直接跳过初始化步骤,永远无法完成初始化,只能重启服务恢复。
如果想要用AtomicBoolean实现和原DCL完全一致的效果,要么保留原来的双重检查+synchronized的结构,只是把变量替换成AtomicBoolean;要么需要额外增加状态标记(比如区分未初始化、初始化中、已初始化三个状态),并让CAS失败的线程等待初始化完成,逻辑会比原生DCL更复杂。
内容的提问来源于stack exchange,提问作者waynewing
相关产品推荐
相关产品推荐

