线程安全的单例模式

双重检查加锁
 
public class Singleton {     

   /**    

   * 对保存实例的变量添加volatile的修饰    

    */     

   private volatile static Singleton instance = null;      

    private Singleton(){       }     

    public static  Singleton getInstance(){     

     //先检查实例是否存在,如果不存在才进入下面的同步块     

        if(instance == null){     

          //同步块,线程安全地创建实例     

          synchronized(Singleton.class){     

              //再次检查实例是否存在,如果不存在才真正地创建实例     

              if(instance == null){     

                 instance = new Singleton();     

             }     

         }      

        }     

        return instance;     

    }     

}   

 

 

并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。

双重检查加锁机制的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。

双重检查机制,尽可能缩小了同步块的范围。

这里解释一下为什么要判断2次,当两个线程调用getInstance方法时,它们都将通过第一重instance==null的判断,由于同步机制,这2个线程只能有一个进入,另一个排队。而此时如果没有第二重判断,则第一个线程创建了实例,而第二个实例离开队列重新获得锁,则将继续创建实例,这样就没有达到单例的目的。

 

类级内部类

 

    public class Singleton { 
        /** 
         * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 
         * 没有绑定关系,而且只有被调用到时才会装载,从而实现了延迟加载 
         */ 
        private static class SingletonHolder{ 
            /** 
             * 静态初始化器,由JVM来保证线程安全 
             */ 
            private static Singleton instance = new Singleton(); 
        } 
        /** 
         * 私有化构造方法 
         */ 
        private Singleton(){ 
        } 
        public static  Singleton getInstance(){ 
            return SingletonHolder.instance; 
        } 
    }

当getInstance方法第一次被调用的时候,它第一次读取SingletonHolder.instance,导致 SingletonHolder类得到初始化;而这个类在装载并被初始化的时候,会初始化它的静态域,从而创建Singleton的实例,由于是静态的域,因此只会在虚拟机装载类的时候初始化一次,并由虚拟机来保证它的线程安全性。

这个模式的优势在于,getInstance方法并没有被同步,并且只是执行一个域的访问,因此延迟初始化并没有增加任何访问成本

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值