在多线程编程中,单例模式是一种常用的设计模式,用于确保一个类只有一个实例,并提供一个全局访问点。然而,在多线程环境下,如果不正确实现,单例模式可能会遇到并发问题。以下是一些方法来打造线程安全的单例模式,避免并发问题:
1. 懒汉式(线程不安全)
最简单的单例实现是懒汉式,它会在第一次使用时创建实例。但是,在多线程环境中,如果不加锁,可能会创建多个实例。
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
2. 饿汉式(线程安全)
饿汉式是在类加载时就立即初始化单例实例,因此它天生就是线程安全的。
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
3. 懒汉式(线程安全,同步方法)
懒汉式可以通过同步方法来确保线程安全,但这会降低性能,因为每次调用getInstance()时都需要同步。
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
4. 懒汉式(双重校验锁,线程安全)
双重校验锁是一种更高效的线程安全实现方式,它只在实例未创建时同步。
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();
}
}
}
return instance;
}
}
这里使用volatile关键字确保instance变量的可见性和有序性。
5. 静态内部类(线程安全)
静态内部类是一种既简单又高效的线程安全实现方式。
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
当Singleton类被加载时,SingletonHolder类不会被加载。只有在调用getInstance()方法时,SingletonHolder类才会被加载,此时INSTANCE才会被创建。
6. 枚举(线程安全)
使用枚举实现单例是最高级的做法,因为枚举类型在Java中是线程安全的。
public enum Singleton {
INSTANCE;
public void whateverMethod() {
// ...
}
}
枚举类型在加载到JVM时,会自动初始化枚举常量,并且枚举常量是单例的。
通过以上方法,你可以根据具体需求选择合适的线程安全单例实现方式。在实际开发中,建议优先考虑性能和简洁性,选择最合适的单例实现。
