單例模式看這幾個

單例模式是一種常用的軟件設計模式,通過它能夠保證系統中,應用該模式的一個類只有一個實例。

在面試中,本人總共手寫過三種單例模式:懶漢模式、餓漢模式、雙重檢查模式

懶漢模式:顧名思義,當系統需要類的實例的時候纔會進行初始化,否則就不會進行初始化。

public class Singleton {
    private static Singleton singleton = null;

    private Singleton() {}

    public synchronized static Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

餓漢模式:餓漢就是無論系統需不需要,都會準備好該實例

public class Singleton {
	private final static Singleton singleton = new Sinleton();
	private Singleton() {}
	public static Singleton getInstance() {
		return singleton;
	}
}

雙重檢查模式:

public class Singleton {
    private volatile static Singleton singleton = null;
    private Singleton() {}

    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

這個代碼就像進門一樣,那麼你先推開門看看是否可以打開,如果可以打開的話,那麼你就進去,然後上鎖,最後在檢查一遍是否鎖好。

但是本人覺得這個雙重檢查的重心應該實在 volatile 關鍵字上,如果沒有加 volatile 關鍵字,那麼在多線程的環境下就可能會調用失敗。

參考:https://blog.csdn.net/xiaobudian0381/article/details/91403670

一個類進行實例化的時候簡單的來說要進行三步:

  1. 分配內存空間
  2. 初始化對象
  3. 返回該對象的地址

在第二步和第三步中不存在依賴關係,所以可能會發生指令重排的事情,舉例說明:A線程調用 getInstance() 方法,發生了指令重排(第二步 第三部 顛倒),先返回的是該對象的地址。此時,線程B調用 getInstance() 方法,發現 singleton 不是空,直接返回。問題出現了,A線程實例化的時候僅僅返回的是對象的地址,但是並沒有進行初始化,但是線程B不知道,所以出現了錯誤。

但是加了 volatile 關鍵字就可以避免這種情況。關於其他的 volatile 關鍵字的講解,可以參考:

https://blog.csdn.net/xiaobudian0381/article/details/90897800

https://blog.csdn.net/xiaobudian0381/article/details/91348251

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章