1. 程式人生 > 其它 >單例模式的懶漢式在多執行緒的問題

單例模式的懶漢式在多執行緒的問題

單例模式的懶漢式在多執行緒的問題
我們都知道,單例設計模式中有兩種方法,一種是餓漢式,另外一種就是懶漢式,具體如下:

餓漢式:

複製程式碼
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關鍵字解決多執行緒問題,用二次判斷提高效率~