单例的DoubleCheck

本文探讨了懒汉单例模式存在的问题,并通过引入DoubleCheck机制,详细解释了如何利用双重检查锁来确保单例的正确创建,避免多例情况的发生。文中列举了不同同步策略的代码示例,阐述了DoubleCheck在实现单例模式中的关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说道DoubleCheck(双重检查锁),就要从懒汉单例模式说起。

为了解决懒汉模式出现多例的情况,我们最容易想到的就是使用synchronized关键字。

看下面代码:

public class Myobject{

   private static Myobject myobject;
   private Myobject(){}

   synchronized public static Myobject getInstance(){
      
      try{

         if(myobject!=null){
        }else{
            
         Thread.sleep(3000);
         myobject = new Myobject();         

         }           

      }catch(InterruptedException e){

        e.printStackTrace();
     
     }
      return myobject;
  }


}

使用上面的同步方法可以实现单例模式,但是这种方法的运行效率非常低,下一个线程想要得到对象,必须等到上一个线程释放锁以后,才可以继续执行。


为了解决上面的问题,可以使用同步代码块,减小同步的颗粒度。

看下面代码:

public class Myobject{

   private static Myobject myobject;
   private Myobject(){}

    public static Myobject getInstance(){
      
      try{

       synchronized(Myobject.class){
           if(myobject!=null){
            }else{
            
            Thread.sleep(3000);
            myobject = new Myobject();         

           }  


      }          

      }catch(InterruptedException e){

        e.printStackTrace();
     
     }
      return myObject;
  }


}

此方法使用同步语句块,只对实例化对象的关键代码进行同步,但是同步颗粒度也很大。所以我们可以只对关键代码进行同步。

看下面的例子:

public class Myobject{

   private static Myobject myobject;
   private Myobject(){}

    public static Myobject getInstance(){
      
      try{
      
           if(myobject!=null){
            }else{     
            Thread.sleep(3000);
        synchronized(Myobject.class){
            myobject = new Myobject();         
            }
           }  
        

      }catch(InterruptedException e){

        e.printStackTrace();
     
     }
      return myObject;
  }


}

上面的方法同步颗粒度确实很小,但是无法实现单例,那我们证明一下:

public class MyThread extends Thread{

  public void run(){

     System.out.println(Myobject.getInstance().hashcode());   
   
   }

}

public class run{
    
  public static void main(String[] args){

       MyThread  t1 = new MyThread();
       MyThread  t2 = new MyThread();
       MyThread  t3 = new MyThread();
       t1.start();
       t2.start();
       t3.start();

  }


   }

运行结果:

         7214088

         15020296

          16130931

那么如何才能解决上面的问题呢,这时候就要用到DoubleCheck机制了(差点儿就忘了这篇博文讲的啥了。。。。)

看下面代码:

public class Myobject{

   private static Myobject myobject;
   private Myobject(){}

    public static Myobject getInstance(){
      
      try{
      
           if(myobject!=null){
            }else{
            
            Thread.sleep(3000);
        synchronized(Myobject.class){
            if(myobject==null)
            myobject = new Myobject();         
            }
           }  
        

      }catch(InterruptedException e){

        e.printStackTrace();
     
     }
      return myObject;
  }


}


这就是DoubleCheck模式,它可以解决懒汉模式的多线程问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值