·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设开发 >> ASP.NET网站开发 >> 设计模式C#实现(六)——单例模式

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

作者:佚名      ASP.NET网站开发编辑:admin      更新时间:2022-07-23

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

 

构成:

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.单例利于维护状态信息