首页 > 代码库 > 线程安全且按需构建的单例模式

线程安全且按需构建的单例模式

单例模式,即保证某个类只有一个实例,网上有很多构造单例的方法,或多或少有其缺陷。如DCL(double check lock)模式,不能保证对象能被正确发布。

使用静态变量

public class CarFactory {
  private static CarFactory instance = new CarFactory();
  private CarFactory(){
  }
  public static CarFactory getInstance(){
    return instance;
  }
}

这个能保证安全性,但是在不需要引用对象的instance时,对象也可能被创建,会造成资源浪费

Double Check Lock(DCL)

public class CarFactory {
  private static CarFactory instance = null;
  private CarFactory(){
  }
  public static CarFactory getInstance(){
    if(instance == null){
      synchronized (CarFactory.class){
        if(instance == null){
          instance = new CarFactory();
        }
      }
    }
    return instance;
  }
}

这个是网上流传的非常广泛的单例模式构造方法,据说既能保证安全性,又能按需创建。但是仔细想想,在线程A和线程B同时调用getInstance()方法时,线程A调用了instance = new CarFactory(),但是对象还没有初始化完毕,这时instance已经不为null,而线程B会认为instance不为null,直接使用instance。这就会造成引用逸出,根据JMM,线程A中初始的数据对线程B的可见性没法保证。这可能会产生很严重的后果

线程安全&&按需创建

public class CarFactory {
  private CarFactory(){
  }
  public static class SingleInstance{
    static CarFactory instance = new CarFactory();
  }
  public static CarFactory getInstance(){
    return SingleInstance.instance;
  }
}
只有在调用getInstance()方法时,才能创建CarFactory实例,而且保证了线程安全性。

线程安全且按需构建的单例模式