Singleton设计模式的C#实现(2)

Singleton设计模式的C#实现(2)


作者: 张申  &;nbsp来自:网络


                (接上部分)
 
  以下为Main函数,本程序的测试入口:
 
  using System;
 
  namespace csPattern.Singleton
 
  {
 
      public class RunMain
 
      {
 
                  public RunMain() {}
 
                  static public void Main(string[] args)
 
                  {
 
                              MutileThread.MutileClient myClient = new MutileThread.MutileClient();
 
                              myClient.ClientMain();
 
                              System.Console.ReadLine();
 
                  }
 
      }
 
  }
 
 
 
  执行结果如下:
 
  线程Thread 1报告: 当前counter为: 2
 
  线程Thread 1报告: 当前counter为: 4
 
  线程Thread 1报告: 当前counter为: 5
 
  线程Thread 1报告: 当前counter为: 6
 
  线程Thread 3报告: 当前counter为: 7
 
  线程Thread 3报告: 当前counter为: 8
 
  线程Thread 3报告: 当前counter为: 9
 
  线程Thread 3报告: 当前counter为: 10
 
  线程Thread 0报告: 当前counter为: 1
 
  线程Thread 0报告: 当前counter为: 11
 
  线程Thread 0报告: 当前counter为: 12
 
  线程Thread 0报告: 当前counter为: 13
 
  线程Thread 2报告: 当前counter为: 3
 
  线程Thread 2报告: 当前counter为: 14
 
  线程Thread 2报告: 当前counter为: 15
 
  线程Thread 2报告: 当前counter为: 16
 
 
 
  由于系统线程调度的不同,每次的执行结果也不同,但是最终结果一定是16。
 
  方法一中由于实例一开始就被创建,所以instance()方法无需再去判断是否已经存在唯一的实例,而返回该实例,所以不会出现计数器类多次实例化的问题。
 
 
 
  使用方法二:
 
  using System;
 
  using System.Threading;
 
  using System.Runtime.CompilerServices;
 
  namespace csPattern.Singleton
 
  {
 
      public class Counter_lazy
 
      {
 
                  static Counter_lazy uniCounter;
 
                  private int totNum = 0;
 
                  private Counter_lazy()
 
                  {
 
                              Thread.Sleep(100);        //假设多线程的时候因某种原因阻塞100毫秒
 
                  }
 
                  [MethodImpl(MethodImplOptions.Synchronized)] //方法的同步属性
 
                  static public Counter_lazy instance()
 
                  {
 
                              if (null == uniCounter)
 
                              {
 
                                          uniCounter = new Counter_lazy();
 
                              }
 
                              return uniCounter;
 
                  }
 
                  public void Inc() { totNum  ;}
 
                  public int GetCounter() { return totNum;}
 
      }
 
  }
 
  不知道大家有没有注意到instance()方法上方的[MethodImpl(MethodImplOptions.Synchronized)] 语句,他就是同步的要点,他指定了instance()方法同时只能被一个线程使用,这样就避免了线程0调用instance()创建完成实例前线程1就来调用instance()试图获得该实例。
 
  根据MSDN的提示,也可以使用lock关键字进行线程的加锁,代码如下:
 
  using System;
 
  using System.Threading;
 
  namespace csPattern.Singleton
 
  {
 
      public class Counter_lazy
 
      {
 
                  static Counter_lazy uniCounter;
 
                  static object myObject = new object();
 
                  private int totNum = 0;
 
                  private Counter_lazy()
 
                  {
 
                              Thread.Sleep(100);        //假设多线程的时候因某种原因阻塞100毫秒
 
                  }
 
                  static public Counter_lazy instance()
 
                  {
 
                              lock(myObject)
 
                              {
 
                                          if (null == uniCounter)
 
                                          {
 
                                                      uniCounter = new Counter_lazy();
 
                                          }
 
                                          return uniCounter;
 
                              }
 
                  }
 
                  public void Inc() { totNum  ;}
 
                  public int GetCounter() { return totNum;}
 
      }
 
  }
 
 
 
  lock()是对一个对象加互斥锁,只允许一个线程访问其后大括号中语句块,直到该语句块的代码执行完才解锁,解锁后才允许其他的线程执行其语句块。
 
  还可以使用Mutex类进行同步,定义private static Mutex mut = new Mutex();后,修改instance()如下,同样可以得到正确的结果:
 
                  static public Counter_lazy instance()
 
                  {
 
                              mut.WaitOne();
 
                              if (null == uniCounter)
 
                              {
 
                                          uniCounter = new Counter_lazy();
 
                              }
 
                              mut.ReleaseMutex();
 
                              return uniCounter;
 
                  }
 
  注意的是,本例中使用方法二要更改方法一的客户程序,去掉Counter_lazy.intance()的注释,并将Counter.intance()注释。
 
  singleton模式还可以拓展,只要稍加修改,就可以限制在某个应用中只能允许m个实例存在,而且为m个实例提供全局透明的访问方法。
 
 
 
    (2005-5-06:06:57)
 感谢原创者的辛勤劳动,希望对您有所帮助,转载请注明原出处。
 警告:持续变种木马正在发起农历新年攻势!
 您可能对 [C#] 的这些文章也感兴趣:
论C#变得越来越臃肿是不可避免的
查询IP所在区段(C#)
在C#中利用SharpZipLib进行文件的压缩和解压缩
C# - Append a host header by code in IIS
在C#中调用Microsoft.VisualBasic命名空间下的类型验证函数
使用泛型实现单例提供者(原创翻译)
C#2 anonymous methods
Master Pages: Tips, Tricks, and Traps
Microsoft .NET 框架资源基础
基于.Net平台应用程序唯一运行实例实现
.net Framework 2.0 专门提供了配置文件的操作
正确实现 IDisposable