Java开发-面试题-0047-单例模式中为什么要使用双重检验锁
更多内容欢迎关注我(持续更新中,欢迎Star✨)
Github:CodeZeng1998/Java-Developer-Work-Note
(技术)微信公众号:CodeZeng1998
(生活)微信公众号:好锅
其他平台:CodeZeng1998、好锅
代码
双重检验锁保证的单例模式代码如下:
public class Singleton {
private static volatile Singleton instance; // volatile防止指令重排序
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) { // 第一次检查(无同步)
synchronized (Singleton.class) { // 同步块
if (instance == null) { // 第二次检查(同步后)
instance = new Singleton(); // 初始化
}
}
}
return instance;
}
}
双重检验锁(Double-Checked Locking),主要用于在多线程环境下保证线程安全的单例初始化,同时优化性能。它的核心目标是确保以下两点:
1. 线程安全
- 避免多线程并发创建多个实例:在单例模式中,如果没有正确的同步机制,多个线程可能同时通过
if (instance == null)
判断,导致创建多个实例。双重检验锁通过同步块(如synchronized
)保证同一时间只有一个线程进入创建实例的代码块。
2. 性能优化
- 减少不必要的同步开销:第一次检查(
if (instance == null)
)在同步块外执行,避免每次访问单例时都进行同步。只有当实例未创建时,才进入同步块进行第二次检查和初始化。
关键点解析
- 双重检验的必要性:
- 第一次检查:快速返回已创建的实例,避免不必要的同步。
- 第二次检查:确保在同步块内只有第一个线程能创建实例,后续线程不会重复创建。
volatile
关键字:- 防止 JVM 指令重排序。若未使用
volatile
,可能出现实例未完全初始化就被其他线程使用的情况。
- 防止 JVM 指令重排序。若未使用
适用场景
- 懒加载单例:实例初始化成本高,需延迟到首次使用时创建。
- 多线程环境:需要线程安全且追求高性能的场景。
总结
双重检验锁通过 “先检查后同步” 的策略,在保证线程安全的同时减少了同步带来的性能损耗,是平衡线程安全与性能的经典解决方案。
以上就是本文相关的所有内容了,如果发现有误欢迎评论指正,更多内容欢迎各位关注。
更多内容欢迎关注我(持续更新中,欢迎Star✨)
Github:CodeZeng1998/Java-Developer-Work-Note
(技术)微信公众号:CodeZeng1998
(生活)微信公众号:好锅
其他平台:CodeZeng1998、好锅