MST

星途 面试题库

面试题:Java 单例模式在多线程环境下的安全实现及优化

在多线程环境中,常规的懒汉式单例模式会存在线程安全问题。请详细说明问题产生的原因,并给出至少两种解决多线程环境下单例模式线程安全问题的优化方案,同时分析每种方案的优缺点。
44.6万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

问题产生原因

在多线程环境下,当多个线程同时访问懒汉式单例模式的getInstance方法时,由于该方法在实例未创建时会进行实例化操作。如果多个线程同时判断实例为空,就会各自创建一个实例,导致单例模式失效,破坏了单例的唯一性。

优化方案

  1. 饿汉式单例
    • 实现代码
public class Singleton {
    private static final Singleton instance = new Singleton();
    private Singleton() {}
    public static Singleton getInstance() {
        return instance;
    }
}
- **优点**:线程安全,在类加载时就创建实例,避免了多线程竞争问题。
- **缺点**:不管是否使用该实例,类加载时就会创建,可能造成资源浪费。

2. 静态内部类单例 - 实现代码

public class Singleton {
    private Singleton() {}
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
- **优点**:线程安全,延迟加载,只有在调用`getInstance`方法时才会加载内部类并创建实例。
- **缺点**:相比其他简单实现,代码结构稍复杂。

3. 双重检查锁定(DCL) - 实现代码

public class Singleton {
    private volatile static Singleton instance;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
- **优点**:延迟加载,线程安全,在第一次检查实例为空时才进行同步操作,提高了性能。
- **缺点**:实现较复杂,需要注意`volatile`关键字的使用,防止指令重排导致获取到未初始化完全的实例。