天天看點

懶漢式單例模式--雙重檢查鎖

懶漢式單例模式–雙重檢查鎖

public final class Singleton {
 	private Singleton() { }
 	private static volatile Singleton INSTANCE = null;
 	public static Singleton getInstance() {
 		// 執行個體沒建立,才會進入内部的 synchronized代碼塊
	 	if (INSTANCE == null) { 
	 		synchronized (Singleton.class) { // t2
		 		// 也許有其它線程已經建立執行個體,是以再判斷一次
		 		if (INSTANCE == null) { // t1
					INSTANCE = new Singleton();
				 }
 			}
		}
		return INSTANCE;
	}
}
           

要點:

  • volatile:可見性、有序性
  • static:靜态的(懶漢式)
  • synchronized:原子性、可見性、有序性
  • 雙重檢查:兩個 if 判斷

實作特點:

  • 懶惰執行個體化(static)
  • 首次使用 getInstance() 才使用 synchronized 加鎖,後續使用時無需加鎖

讀寫 volatile 變量時會加入記憶體屏障(Memory Barrier(Memory Fence)),保證下面兩點:

  • 可見性
    • 寫屏障(sfence)保證在該屏障之前的 t1 對共享變量的改動,都同步到主存當中
    • 而讀屏障(lfence)保證在該屏障之後 t2 對共享變量的讀取,加載的是主存中最新資料
  • 有序性
    • 寫屏障會確定指令重排序時,不會将寫屏障之前的代碼排在寫屏障之後
    • 讀屏障會確定指令重排序時,不會将讀屏障之後的代碼排在讀屏障之前
  • 更底層是讀寫變量時使用 lock 指令來多核 CPU 之間的可見性與有序性