如何使用双重检查锁定在 Java 中创建线程安全的单例?
参考答案:
双重检查锁定 (Double-Checked Locking) 是一种在 Java 中实现线程安全单例模式的常见方法。这种方法结合了延迟初始化和锁机制,可以在多线程环境下安全地创建单例实例。
下面是一个使用双重检查锁定实现单例模式的示例代码:
public class Singleton {
private static volatile Singleton instance;
private Singleton() {
// 私有构造函数,防止外部通过 new Singleton() 创建实例
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
这里的关键点有:
private static volatile Singleton instance;
:使用volatile
关键字确保instance
变量的可见性。在多线程环境下,当一个线程修改了一个共享变量的值,其他线程能够立即看到修改后的值。volatile
可以防止 JVM 对指令进行重排序,从而确保在多线程环境下创建单例实例的正确性。private Singleton()
:将构造函数设置为私有,防止外部通过new Singleton()
创建实例。public static Singleton getInstance()
:提供一个静态方法用于获取单例实例。在方法中,首先检查instance
是否为null
,如果是,则进入同步块。在同步块内,再次检查instance
是否为null
,如果是,则创建一个新的Singleton
实例并赋值给instance
。这样做的好处是,当instance
已经被初始化后,后续的线程无需再进入同步块,从而提高了性能。
需要注意的是,双重检查锁定虽然可以提高性能,但在 Java 1.5 之前的版本中,由于 JVM 对 volatile
的实现可能存在问题,双重检查锁定可能无法正常工作。因此,在 Java 1.5 及以后的版本中,双重检查锁定是安全的。如果你使用的是 Java 1.5 之前的版本,建议使用其他方式实现线程安全的单例模式,如饿汉式或懒汉式加锁。