欢迎光临
我的个人博客网站

设计模式 – 18)单例模式

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;     } } 

1. 多线程同时创建实例问题

多个线程同时访问 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)。 

2. 每次实例都要锁的性能问题

使用双重锁定,只有未实例化时才锁,锁完判断是否还未实例化。

public static Singleton GetInstance() {     if (_singleton == null)     {         lock (syncRoot)         {             if (_singleton == null)             {                 _singleton = new Singleton();             }         }     }     return _singleton; } 

3.饿汉式单例

class Singleton {     static readonly Singleton _instance = new Singleton();      private Singleton() { }      public static Singleton GetInstance()     {                     return _instance;     } } 

这种静态初始化的方式是自己被加载时就将自己实例化,因此被称为饿汉式单例;
而第一次被引用时才将自己实例化的方式被称为懒汉式单例。C# 中饿汉式已足够满足。

赞(0) 打赏
未经允许不得转载:张拓的天空 » 设计模式 – 18)单例模式
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

专业的IT技术经验分享 更专业 更方便

联系我们本站主机

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏