单例模式
1. 双重检查
java
public class Singleton {
// 使用 volatile 修饰,防止指令重排序
private static volatile Singleton instance;
// 私有化构造方法,防止外部直接实例化
private Singleton() {}
// 提供全局访问点
public static Singleton getInstance() {
if (instance == null) { // 第一次检查
synchronized (Singleton.class) {
if (instance == null) { // 第二次检查
instance = new Singleton();
}
}
}
return instance;
}
}
代码解析
- volatile 关键字:
- 防止指令重排序。
- 在没有 volatile 修饰时,instance = new Singleton(); 可能会分为以下三个步骤:
- 分配内存。
- 初始化对象。
- 将内存地址赋值给 instance。
- 如果重排序发生(步骤 2 和步骤 3 调换顺序),可能会导致其他线程获取到未完全初始化的对象。
- 双重检查锁的意义:
- 第一次检查:避免不必要的加锁操作,提高性能。
- 第二次检查:确保线程安全,防止多个线程同时进入同步块导致重复实例化。
- 私有构造方法:
- 防止外部直接调用构造器创建实例。
- 线程安全性:
- 使用 synchronized 确保线程安全。
优点
- 线程安全:在多线程环境下可以安全使用。
- 性能高:通过双重检查锁机制,只有在 instance 为 null 时才加锁,避免了每次调用方法都加锁的性能开销。