单例设计模式

243 阅读2分钟

1、什么是单例模式

简单来说,单例模式就是一个类只能构建一个对象的设计模式。

2、单例模式第一版:

public class Singleton_V1{
 private Singleton_V1(){}//私有构造函数
 private static Singleton_V1 instance=null;//单例对象
//静态工厂方法
 public static Singleton_V1 GetInstance(){
   if(instance==null){
     instance=new Singleton_V1();
   }
   return instance;
 }
}

为什么这样写,下面我们来解释一下:

1、要想让一个类只能构建一个对象,就不能让其随便的去做new操作,因此Singleton_V1的构造方法是私有的。

2、instance是Singleton_V1类的静态成员,也就是我们的单例对象。他的初始值可以写成null,也可以写成new Singleton_V1().

3、getInstance()是获取单例对象的方法。

如果单例初始值是null,还未构建,则构建单例对象并返回。这个写法即是private static Singleton instance=null;的方式。也叫懒汉模式。

如果单例对象一开始就被new Singleton()主动构建。则不再需要做判空的操作。这个写法即是private static Singleton instance=new Singleton();的方式,也就是上文所说的instancec初始值可以为null,也可以为new Singleton()的区别。也叫饿汉模式。

3、单例模式第二版

第一版的写法虽然实现了单例模式,但是并不是线程安全的,因为假如Singleton类刚刚被初始化,instance对象还是空,这时候两个线程同时访问getInstance方法:

preview

由上图可知:此时因为Instance是空,所以两个线程同时通过了判断,开始执行new操作,这样的话,instance就会被构建了两次。所以,要想线程安全的话,我需要对代码做进一步的优化。

单例模式第二版:

public class Singleton_V2{
 private Singleton_V2(){}//私有函数构造
 private static Singleton_V2 instance=null;//单例对象
 //静态工厂方法
 public Singleton_V2 GetInstance(){
  if(instance==null){//双重检测机制
    lock(Singleton_V2.class){//同步锁
    if(instance==null){
     instance=new Singleton_V2();
    }
   }
  }
  return instance;
 }
}

根据以上代码我们来解释为什么这样写就是线程安全的:

1、为了防止new Singleton被执行多次,因此在new操作之前加上lock同步锁,锁住整个类

2、进入lock临界区以后,还要在做一次判空。因为当两个线程同时被访问的时候。线程A构建完对象,,线程B也已经通过了最初的判空验证,不做第二次判空的话,线程B还是会再次构建instance对象。


preview

preview

preview