由浅到深的单例模式

前言:说起单例模式,可能大家都熟悉,可以说是设计模式中出现频率最高的一个,为了彻底弄清单例,在这里我将说明何为单例,单例模式的演变,已经和静态类之间的区别等。

1:概念

何为单例,就是在一个应用程序中只能有一个实例,就是保证对象只能被new一次。

2:懒汉模式

懒汉我觉得这个名字很形象,就是很懒,所以别的对象加载,它就不加载,你调用我的时候我在加载。比喻hibernate中也有懒模式。ok我们开始吧

2.1:非线程安全

一天小明去面试,面试官说,你给我写个单例模式,小明一想这实在太简单了不暇思索很快写出来了如下的单例模式

1 public class Singleton { 2 private static Singleton singleton; 3 public static Singleton getSingleton() 4 { 5 if(singleton==null) 6 { 7 singleton=new Singleton(); 8 } 9 return singleton; 10 } 11 }

然后面试官一看说:你这在高并发的时候有可能会产生多个singleton实例,小明一想怎么会呢,面试官解释说,如果有2个线程T1,T2同时执行,当T1执行到第6行的时候,时间片段到,系统开始让T2执行,执行到第9行,然后T1又开始执行,因为T1已结做过判断此时并不知道singleton已结被实例化,所以singleton此时再次被实例化,这样你系统就有2个singleton对象,那还是单例吗,小明恍然大悟,这个我能解决,马上又写出下面这个

2.2:线程安全

1 public class Singleton { 2 private static Singleton singleton; 3 4 public synchronized static Singleton getSingleton() 5 { 6 if(singleton==null) 7 { 8 singleton=new Singleton(); 9 } 10 return singleton; 11 }

面试官一看,加上了线程同步,这个时候确实能保证线程安全问题,但是又提出了疑问,如果现在singleton已经被实例化了,如果10个线程同时访问,每次都要等待那么势必造成性能极大的消耗,你有没有别的方案解决问题,小明思考一分钟又写下了下面一段代码

2.3:双重校验

1 public class Singleton { 2 private static Singleton singleton; 3 4 public static Singleton getSingleton() 5 { 6 if(singleton==null) 7 { 8 synchronized (Singleton.class) { 9 if(singleton==null) 10 { 11 singleton=new Singleton(); 12 } 13 } 14 } 15 return singleton; 16 }

面试官一看,果真在上面一段代码的基础上提升了不少性能,减少了不必要的等待,但是仔细一看说你这代码有点问题,并不能保证线程的安全,小明说怎么说呢,然后面试官解释说:如果有T1,T2两个线程,T1线程运行第六行发现singleton==null,就进入第8行,开始对singleton进行实例化,因为实例化中分为三步,第一步为对象开辟内存空间,第二步为对象初始化,第三步是把这个内存地址赋给singleton,但是因为Java的内存模式允许无序写入,这样一来会导致第二步和第三步位置调换,那么这样一来就坏了,如果先允许第一步和第三步了,但是此时并没有对对象进行初始化,恰恰在此时T2进入了第6行,经过判断singleton不为null,那么就会返回一个没有被初始化的对象。小明听了觉得对啊,他说我把内存模式改为不允许无序写入不就行了吗,于是就把代码修改为

1 public class Singleton { 2 private volatile static Singleton singleton;//表示有序写入 3 4 public static Singleton getSingleton() 5 { 6 if(singleton==null) 7 { 8 synchronized (Singleton.class) { 9 if(singleton==null) 10 { 11 singleton=new Singleton(); 12 } 13 } 14 } 15 return singleton; 16 }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/3dd0c8295335a8b0577d9b4ff3c306c9.html