单例模式及双重锁定了解一下

今天来写写单例吧,其实之前设计模式也看了很多,但是平常不太用到,而且不注意做笔记,所以总是反反复复会忘记,最近在准备面试,那再看一遍总结一下吧。

首先单例模式就是说一个类只能有一个实例对象。

单例模式有两种实现方法:饿汉模式和懒汉模式

饿汉模式:在类加载时就完成了初始化,所以类加载速度比较慢,但是获取对象速度比较快

                   因为类加载时已经完成了初始化,所以不需要判断对象是否为空,不需要同步

1 //饿汉模式示例代码
2 Class Single{
3      private static Single s=new Single();//类加载时已进行初始化。s为私有静态成员变量
4      private Single(){}//构造方法为私有的,使得其他类无法通过new产生对象
5      public static Single getInstance(){
6            return s;
7       }                                 
8 }

懒汉模式:在类加载时不需要创建实例,在第一次调用时再创建

 1 Class  LazySingle{
 2     private static LazySingle ls;
 3     private LazySingle(){}
 4     public static LazySingle getInstance(){
 5            if(ls==null){
 6                  ls=new LazySingle();
 7            }
 8            return ls;
 9      }
10 }

懒汉模式的问题在于不同步,如果有多个线程同时掉用getInstance方法时,无法保证单例。

此时可以在getInstance方法上加sychonized锁进行同步,也就是将上述代码第四行变为public static sychonized LazySingle getInstance(){

但是直接在方法上加锁势必会影响性能,因为实例对象如果不为空可以不用锁,直接返回已有实例就可以了。所以就有了双重锁定,先上代码再解释。

 Class  LazySingle{
     private static LazySingle ls;
     private static Object o=new Object();
     private LazySingle(){}
     public static LazySingle getInstance(){
            if(ls==null){
                sychonized(o){
                   if(ls==null)
                   ls=new LazySingle();
               }   
          }
             resturn ls;
       }
 }

个人认为叫双重锁定不如叫双重判断来的直接。

首先为了不影响性能,仅在ls为空时加锁,这就是第一层判断的作用。

但是仅有第一层判断就足够了吗?试想现在有两个线程同时到达第一层判断,则两个线程都可以通过第一层判断,这时就需要加锁进行同步,一个一个进,先到达的线程执行第二层判断,此时ls为null,则进行实例化。执行后,后达到的线程再执行第二层的判断,此时发现ls已经不为空了,所以直接返回ls.综上所述,第一层判断是为了判断是否需要加锁,第二层判断是为了判断是否需要进行实例化

另外再说为什么要新建一个对象来加锁,因为在加锁时ls还未进行实例化,即实例还不存在,所以只能通过新建一个对象进行实例化。

 

posted @ 2018-09-06 11:19  朝朝暮暮dx  阅读(786)  评论(0编辑  收藏  举报