單例模式之懶漢的併發問題
阿新 • • 發佈:2019-02-18
餓漢模式: 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;
}
}