單例模式的懶漢式在多執行緒的問題
單例模式的懶漢式在多執行緒的問題
我們都知道,單例設計模式中有兩種方法,一種是餓漢式,另外一種就是懶漢式,具體如下:
餓漢式:
複製程式碼
package com.seven.exercise.testEception;
/**
- 單例模式,餓漢式
- @author Seven
*/
public class SingleDemoHunger {
private SingleDemoHunger() { } private static SingleDemoHunger sdh = new SingleDemoHunger(); public static SingleDemoHunger getInstance() { return sdh; }
}
複製程式碼
懶漢式:
複製程式碼
package com.seven.exercise.testEception;
/**
- 懶漢式
- @author Seven
*/
public class SingleDemo {
/** * 私有化建構函式 */ private SingleDemo(){ } private static SingleDemo singleDemo = null; /** * 提供獲取例項的方法 * @return */ public static SingleDemo getInstance(){ if(singleDemo==null){ singleDemo = new SingleDemo(); } return singleDemo; }
}
複製程式碼
相信這兩種方法大家都知道,但是沒有有考慮過在多執行緒的情況下:
餓漢式屬於立即載入,所以不存在在多執行緒中出現錯誤的情況;
但是懶漢式的話就有可能出現問題了,如多一個執行緒執行到判斷是否為空的語句
if(singleDemo==null)
的時候,當前執行緒被阻塞,而第二個執行緒進來了,這樣的話第二個執行緒建立了新的物件,那麼第一個執行緒被喚醒的時候又建立多一個物件,這樣在記憶體中就存在了兩個物件,明顯和單例設計模式不符,那麼我們應該怎麼做呢?
很簡單,用 synchronized關鍵字就可以輕鬆解決:
複製程式碼
package com.seven.exercise.testEception;
/**
- 懶漢式
- @author Seven
*/
public class SingleDemo {
/**
* 私有化建構函式
*/
private SingleDemo(){
}
private static SingleDemo singleDemo = null;
/**
* 提供獲取例項的方法,用synchronized來解決多執行緒的問題.
* @return
*/
public static SingleDemo getInstance(){
synchronized (SingleDemo.class) {
if(singleDemo==null){
singleDemo = new SingleDemo();
}
}
return singleDemo;
}
}
複製程式碼
這樣就減少了建立多個例項的可能,但是還是存在建立多個例項的可能性,而且同步鎖肯定要消耗資源,這樣的話就會降低效率,那麼有什麼辦法可以提高效率呢?答案是有的,那就是通過二次判斷,這樣的話就不用每次都執行同步程式碼塊,這樣的話,只需第一次執行的時候比較佔資源,以後的話就和之前的一樣了:
複製程式碼
package com.seven.exercise.testEception;
/**
- 懶漢式
- @author Seven
*/
public class SingleDemo {
/**
* 私有化建構函式
*/
private SingleDemo(){
}
private static SingleDemo singleDemo = null;
/**
* 提供獲取例項的方法,用synchronized來解決多執行緒的問題.
* @return
*/
public static SingleDemo getInstance(){
//二次判斷提高效率
if(singleDemo==null){
synchronized (SingleDemo.class) {
if(singleDemo==null){
singleDemo = new SingleDemo();
}
}
}
return singleDemo;
}
}
複製程式碼
所以,利用synchronized關鍵字解決多執行緒問題,用二次判斷提高效率~