3.單例模式的多種寫法
阿新 • • 發佈:2019-02-03
-
不加同步的懶漢式是執行緒不安全的。比如,有兩個執行緒,一個是執行緒A,一個是執行緒B,它們同時呼叫getInstance方法,就可能導致併發問題。
-
餓漢式是執行緒安全的,因為虛擬機器保證只會裝載一次,在裝載類的時候是不會發生併發的。
如何實現懶漢式的執行緒安全?
加上synchronized即可
public static synchronized Singleton getInstance(){}
但這樣會降低整個訪問的速度,而且每次都要判斷。可以用雙重檢查加鎖。
雙重加鎖機制,指的是:並不是每次進入getInstance方法都需要同步,而是先不同步,進入方法過後,先檢查例項是否存在,如果不存在才進入下面的同步塊,這是第一重檢查。進入同步塊後,再次檢查例項是否存在,如果不存在,就在同步的情況下建立一個例項。這是第二重檢查。
雙重加鎖機制的實現會使用一個關鍵字volatile,它的意思是:被volatile修飾的變數的值,將不會被本地執行緒快取,所有對該變數的讀寫都是直接操作共享記憶體,從而確保多個執行緒能正確的處理該變數。
/** * 雙重檢查加鎖的單例模式 * @author dream * */ public class Singleton { /** * 對儲存例項的變數新增volitile的修飾 */ private volatile static Singleton instance = null; private Singleton(){ } public static Singleton getInstance(){ //先檢查例項是否存在,如果不存在才進入下面的同步塊 if(instance == null){ //同步塊,執行緒安全的建立例項 synchronized (Singleton.class) { //再次檢查例項是否存在,如果不存在才真正的建立例項 instance = new Singleton(); } } return instance; } }
一種更好的單例實現方式
public class Singleton { /** * 類級的內部類,也就是靜態類的成員式內部類,該內部類的例項與外部類的例項 * 沒有繫結關係,而且只有被呼叫時才會裝載,從而實現了延遲載入 * @author dream * */ private static class SingletonHolder{ /** * 靜態初始化器,由JVM來保證執行緒安全 */ private static final Singleton instance = new Singleton(); } /** * 私有化構造方法 */ private Singleton(){ } public static Singleton getInstance(){ return SingletonHolder.instance; } }