双重检查锁定(DCL)单例需用volatile修饰实例并执行两次null检查:第一次在同步外避免无谓加锁,第二次在同步内防止多线程重复创建;volatile禁止重排序并保证可见性,缺一则DCL失效。
在
java
中,双重检查锁定(double-checked locking, dcl)是一种常见的单例实现方式,它通过
语句配合
块实现线程安全且延迟初始化。关键在于两次
判断:第一次避免无谓加锁,第二次确保实例唯一性。
第一次 if:避免不必要的同步开销
在获取实例时,先检查实例是否已创建。若已存在,直接返回,跳过同步块,提升性能。
这是 DCL 的“第一重检查”,发生在同步块外
必须用
修饰单例引用,防止指令重排序导致其他线程看到未初始化完成的对象
示例逻辑:
同步块内第二次 if:保证实例创建的原子性
进入同步块后,再次检查实例是否为
。因为可能多个线程同时通过了第一次检查,只有第一个进入的线程应创建实例。
这是“第二重检查”,防止多线程重复初始化
构造逻辑必须放在该
内,例如
若省略此检查,可能出现多个实例,破坏单例语义
volatile 关键字不可省略
不仅禁止指令重排序,还保证可见性:一个线程对
的写入能立即被其他线程看到。
没有
,JVM 可能将对象分配内存、调用构造器、赋值给引用三步重排序,导致其他线程拿到未完全初始化的对象
即使两次
都存在,缺少
仍会导致 DCL 失效
完整可运行示例
以下是一个标准 DCL 单例实现,含必要注释说明
控制点:
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
立即学习
“
Java免费学习笔记(深入)
”;
}
ifsynchronizedifvolatileif (instance == null) { /* 进入同步块 */ }nullifinstance = new Singleton();volatileinstancevolatileifvolatileif
public class Singleton {
private static volatile Singleton instance;
private Singleton() {} // 私有构造,防止外部实例化
public static Singleton getInstance() {
if (instance == null) { // 第一次检查:无锁,快速返回
synchronized (Singleton.class) {
if (instance == null) { // 第二次检查:加锁后确认,防重复创建
instance = new Singleton(); // 构造实例(volatile 保障安全发布)
}
}
}
return instance;
}