class STWindow { static Window win; private STWindow() { } public static Window GetInstance() { if (win == null || !win.IsVisible) { win = new Window(); win.Height = 200; win.Width = 200; } return win; } } class Singleton { static Singleton _singleton; private Singleton() { } public static Singleton GetInstance() { if (_singleton == null) { _singleton = new Singleton(); } return _singleton; } }
多個線程同時訪問 Singleton 的 GetInstance() 方法,可能會形成建立多個實例;
好比 A 先進入後在準備實例化 Singleton 的過程當中,B 也進入了,這時 _singleton 仍是爲 null,而後 B 也去實例化 Singleton 了。多線程
class Singleton { static Singleton _singleton; private Singleton() { } public static Singleton GetInstance() { if (_singleton == null) { Console.WriteLine("實例化一個 Singleton"); _singleton = new Singleton(); } Console.WriteLine("返回一個 Singleton"); return _singleton; } } System.Threading.Thread a = new System.Threading.Thread(() => { Singleton.GetInstance(); }); System.Threading.Thread b = new System.Threading.Thread(() => { Singleton.GetInstance(); }); System.Threading.Thread c = new System.Threading.Thread(() => { Singleton.GetInstance(); }); a.Start(); b.Start(); c.Start();
實例化一個 Singleton 實例化一個 Singleton 返回一個 Singleton 返回一個 Singleton 返回一個 Singleton
咱們經過加個鎖來解決這個問題。性能
public static readonly object syncRoot = new object(); public static Singleton GetInstance() { lock (syncRoot) { if (_singleton == null) { Console.WriteLine("實例化一個 Singleton"); _singleton = new Singleton(); } } Console.WriteLine("返回一個 Singleton"); return _singleton; }
實例化一個 Singleton 返回一個 Singleton 返回一個 Singleton 線程 0x1a08 已退出,返回值爲 0 (0x0)。 返回一個 Singleton 線程 0x45b4 已退出,返回值爲 0 (0x0)。 線程 0x5a04 已退出,返回值爲 0 (0x0)。
使用雙重鎖定,只有未實例化時才鎖,鎖完判斷是否還未實例化。線程
public static Singleton GetInstance() { if (_singleton == null) { lock (syncRoot) { if (_singleton == null) { _singleton = new Singleton(); } } } return _singleton; }
class Singleton { static readonly Singleton _instance = new Singleton(); private Singleton() { } public static Singleton GetInstance() { return _instance; } }
這種靜態初始化的方式是本身被加載時就將本身實例化,所以被稱爲餓漢式單例;
而第一次被引用時纔將本身實例化的方式被稱爲懶漢式單例。C# 中餓漢式已足夠知足。code