1. 程式人生 > >單例模式之懶漢的併發問題

單例模式之懶漢的併發問題

餓漢模式:

class Single{

  private staitc final Single s= new Single();

  private Single(){}

  public static Single getSingle(){

    return s;

  }

}  

懶漢模式:

class Single{

  private static Single s= null;

  private Single(){}

  public static Single getSingle(){

    if(s == null){

        -->A執行緒

        -->B執行緒

      s  =  new Single();

      return s;

    }  

  }

}

在這裡使用懶漢模式有一個安全性問題:

就是s為共享資料,可能會併發的訪問getSingle()方法。當多執行緒訪問時,一個A執行緒進來後,可能呼叫了sleep()方法在這裡沉睡;一個B執行緒也可能在沉睡,當A執行緒醒來後,就會new一個物件,B執行緒醒來也會new一個物件;這樣就不符合我們單例模式的特點了。

解決方案:使用synchronized方法進行執行緒同步

另一個問題,當加了synchronized後,那麼很多執行緒來訪問時,都要判斷一下鎖是哪個,這就造成速率下降

解決方案:在synchronized方法後新增instance是否為null的判斷,這樣當下一個執行緒訪問時發現instance非空後直接返回前面執行緒例項化後的物件

public staitc Single getSingle(){

  if(s == null){

    synchronized(Single.class){  -->B執行緒,等著A解鎖才讓進去

      if(s == null){

          -->A執行緒

        s = new Single();

      }

    }

  return s;

  }

}