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