ASP.NET C# 单例模式 Singleton 详解

关于单例模式的一些要点:

  • Singleton模式中的实例构造器可以设置为protected以允许子类派生。
  • Singleton模式一般不要支持ICloneable接口,因为这可能会导致多个对象实例,与Singleton模式的初衷违背。
  • Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样跟Singleton模式的初衷违背。
  • Singleton模式只考虑到了对象创建的管理,并没有考虑对象销毁的管理。就支持垃圾回收的平台和对象的开销来讲,我们一般没必要对其销毁进行特殊的管理。

多线程的Singleton模式


  1. public class Singleton  
  2.     {  
  3.         private static volatile Singleton instance = null;  
  4.   
  5.         private static object lockHelper = new object();  
  6.   
  7.         private Singleton() { }  
  8.   
  9.         public static Singleton Instance  
  10.         {  
  11.             get  
  12.             {  
  13.                 if (instance == null)  
  14.                 {  
  15.                     lock (lockHelper)  
  16.                     {  
  17.                         if (instance == null)  
  18.                         {  
  19.                             instance = new Singleton();  
  20.                         }  
  21.                     }  
  22.                 }  
  23.                 return instance;  
  24.             }  
  25.         }  
  26.     }  

代码说明:

  • volatile C#关键字作用,简单来说,编译器编译我们的代码时候,会对代码作一些优化,进而对代码进行了微调,使用volatile关键字就可以避免这个微调。继而严格意义上保证不会产生多线程。更详细的关于volatile 的说明,请看参考资料。
  • 双检查加锁模式。在lock之外和之内,我们做了instance是否为空的检查。这叫双检查。因为同步控制的时间太长了。双检查能够最高效地实现多线程安全的访问。

 使用.net特性的支持多线程的单件模式代码


  1. public sealed class Singleton  
  2.  {  
  3.      public static readonly Singleton Instance = new Singleton();  
  4.      private Singleton() { }  
  5.  }  

代码说明:

  • sealed 修饰符表示该类是密封类,不能被继承。你可以按需修改。
  • 这里readonly关键字只是不希望客户程序将Instance字段设置为null等不合理的值。
  • *** static *** = new Singleton(); 是使用了内联初始化技术,这部分初始化其实是在static Singleton()中执行的。即上面的代码相当于:

    


  1. public sealed class Singleton  
  2.   {  
  3.       public static readonly Singleton Instance;  
  4.       static Singleton()  
  5.       {  
  6.           Instance = new Singleton();  
  7.       }  
  8.       private Singleton() { }  
  9.   }  

     上述代码在编译时,会使用一个名为beforefieldinit元数据标志。此标志使得运行库能够在任何时候执行类型构造函数方法,只要该方法在第一次访问该类型的静态字段之前执行即可。换句话说,beforefieldinit 为运行库提供了一个执行主动优化的许可。如果没有 beforefieldinit,运行库就必须在某个精确时间运行类型构造函数,即,恰好在第一次访问该类型的静态或实例字段和方法之前。

  • 静态构造器自身就可以保证,多线程情况下,系统就可以保证只有一个执行。

缺点:

不支持参数化单件构造器。即静态构造器不支持参数,就导致我们无法利用静态构造器实现传参数的单件。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值