首页 > 学院 > 开发设计 > 正文

设计模式C#实现(六)——单例模式

2019-11-14 15:48:45
字体:
来源:转载
供稿:网友

单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

 

构成:

1.私有的构造函数

2.私有静态的实例

3.返回实例的静态方法

  public class Singleton    {        PRivate static Singleton uniqueInstance = new Singleton();        private Singleton() { Console.WriteLine("this is a new singleton"); }        public static Singleton getInstance()        {            if (uniqueInstance == null)            {                return uniqueInstance;            }            return uniqueInstance;        }    }

 

这种叫做饿汉模式,实例在类加载时就创建了,缺点是如果实例如果消耗大量的资源而没有使用就会造成浪费,另一种懒汉模式,实例在被使用时才创建,

  public class Singleton    {        private static Singleton uniqueInstance;        private Singleton() { Console.WriteLine("this is a new singleton"); }        public static Singleton getInstance()        {            if (uniqueInstance == null)            {                return uniqueInstance = new Singleton();            }            return uniqueInstance;        }    }

但是这不是线程安全的

例如

class Program {             static void Main(string[] args) {            while (true) {                Thread t1 = new Thread(Test);                t1.Start();            }        }        static void Test() {            Singleton s = Singleton.getInstance();        }           }

执行的结果有可能是这样

程序创建了多个实例,这不是我们想要的结果,原因是某个线程if (uniqueInstance == null)语句执行后让出了使用权,当它重新获得CPU使用权的时候,可能别的CPU已经创建了实例,而它并不知道,继续执行return uniqueInstance= new Singleton();导致出现多个实例。

因此,要为方法加锁

  public class Singleton    {        private static Singleton uniqueInstance;        private Singleton() { Console.WriteLine("this is a new singleton"); }        private static readonly object syncRoot = new object();        public static Singleton getInstance()        {            lock (syncRoot)            {                if (uniqueInstance == null)                {                      return uniqueInstance = new Singleton();                }            }            return uniqueInstance;        }    }

但是这又带来了一个问题,在实例已经创建完成了,但还是会有大量的线程卡在lock (syncRoot),它们都还会尝试创建实例,这降低了性能

为此,还要为此方法创建另外一个验证

 public static Singleton getInstance()        {            if (uniqueInstance == null)            {                lock (syncRoot)                {                    if (uniqueInstance == null)                    {                       return uniqueInstance = new Singleton();                    }                }            }            return uniqueInstance;        }

此时,当实例已经创建完成之后,各线程不再访问临界区,提高了性能

 

单例模式和静态类的比较

1.单例模式可以懒加载,静态类执行更快(为什么?),即在不同条件下二者有不同的性能表现

2.单例可以继承和override

3.单例易于模拟,利于测试

4.单例利于维护状态信息

 


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表