在 Java 中实现线程安全的单例模式可以通过几种方式,下面我会展示两种常用的线程安全的单例模式实现:懒汉式和双重检查锁定(Double-Checked Locking)。
1. 懒汉式(Lazy Initialization)
懒汉式是指在第一次使用时才实例化对象。这种方式在多线程环境下如果不加同步控制可能会创建多个实例,因此需要在获取实例时进行同步控制。
public class SingletonLazy {
private static SingletonLazy instance;
private SingletonLazy() {
// 私有构造方法
}
public static synchronized SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
}
- 说明:
getInstance()
方法使用synchronized
关键字确保在多线程环境下只创建一个实例。但是,这种方式效率较低,因为每次调用getInstance()
都需要进行同步,即使实例已经创建。- 懒汉式在单线程环境下表现良好,但在高并发环境下可能存在性能问题。
2. 双重检查锁定(Double-Checked Locking)
双重检查锁定是一种在实例不存在时进行同步锁定的优化方式,避免了每次获取实例都进行同步的性能损耗。
public class SingletonDoubleChecked {
private static volatile SingletonDoubleChecked instance;
private SingletonDoubleChecked() {
// 私有构造方法
}
public static SingletonDoubleChecked getInstance() {
if (instance == null) {
synchronized (SingletonDoubleChecked.class) {
if (instance == null) {
instance = new SingletonDoubleChecked();
}
}
}
return instance;
}
}
- 说明:
- 使用
volatile
关键字修饰instance
变量,保证多线程环境下对变量的可见性。 - 双重检查锁定在实例未创建时才进行同步锁定,避免了每次获取实例都进行同步,提高了性能。
- 双重检查锁定需要 JDK 5 以上版本支持,因为早期的 JDK 对
volatile
关键字的实现可能不稳定。
- 使用
总结:
以上是两种常用的线程安全的单例模式实现方式。在选择时,可以根据具体的需求和场景来决定使用哪种方式。双重检查锁定通常比懒汉式更推荐,因为它在保证线程安全的同时,又能有效地提高性能。