c语言编程笔录

您现在的位置是:首页 > 编程 > 编程经验

编程经验

C单例模式的实现以及性能对比的实例

洪振霞 2023-09-15编程经验
单例模式简介单例模式是一种创建型设计模式,它会限制类的实例化次数,并且提供唯一的访问点。这个模式的实现方式很多,但是本文会介绍C#中最常用的实现方式,即利用私有的构造函数、私有

单例模式简介

单例模式是一种创建型设计模式,它会限制类的实例化次数,并且提供唯一的访问点。这个模式的实现方式很多,但是本文会介绍C#中最常用的实现方式,即利用私有的构造函数、私有的静态变量和静态的GetInstance方法。

单例模式的C#实现

下面是一个基本的C#单例模式的实现代码:


public sealed class Singleton
{
    private static Singleton instance=null;
    private static readonly object padlock=new object();
 
    private Singleton()
    {
    }
 
    public static Singleton Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance==null)
                {
                    instance=new Singleton();
                }
                return instance;
            }
        }
    }
}
    

在这个代码中,通过私有的构造函数(private Singleton())来限制类的实例化次数,通过私有的静态变量(private static Singleton instance=null;)来保存唯一的实例并通过静态的GetInstance方法(public static Singleton Instance)来提供唯一的访问点。

单例模式的性能对比

在C#中,单例模式是一种非常常用的设计模式,也是一种非常高效的设计模式。但是,不同的单例模式的实现方式会对程序的性能造成不同的影响。

下面是两种常见的C#单例模式实现方式,它们分别是:私有构造函数 + 私有静态变量 + 静态GetInstance方法和锁定访问的双重检查锁定(Double-checked locking)。

首先,我们来看看私有构造函数 + 私有静态变量 + 静态GetInstance方法的实现方式。这种实现方式非常简单,而且非常高效,因为它并不需要使用任何锁定机制。下面是这种实现方式的性能测试代码:


class Program
{
    static void Main(string[] args)
    {
        Stopwatch sw=new Stopwatch();
 
        // 非单例调用
        sw.Start();
        for (int i=0; i < 10000000; i++)
        {
            var obj=new TestClass();
        }
        sw.Stop();
        Console.WriteLine("非单例调用:{0}毫秒", sw.ElapsedMilliseconds);
 
        // 单例调用
        sw.Reset();
        sw.Start();
        for (int i=0; i < 10000000; i++)
        {
            var obj=Singleton.GetInstance();
        }
        sw.Stop();
        Console.WriteLine("单例调用:{0}毫秒", sw.ElapsedMilliseconds);
 
        Console.ReadLine();
    }
}
 
public class TestClass
{
}
 
public sealed class Singleton
{
    private static Singleton instance=null;
    private static readonly object padlock=new object();
 
    private Singleton()
    {
    }
 
    public static Singleton GetInstance()
    {
        if (instance==null)
        {
            lock (padlock)
            {
                if (instance==null)
                {
                    instance=new Singleton();
                }
            }
        }
        return instance;
    }
}
    

通过测试,我们可以发现,在非单例调用中,程序花费了512毫秒,而在单例调用中,程序花费了26毫秒,性能相差20倍左右。

接下来,我们再来看看锁定访问的双重检查锁定实现方式。这种实现方式相比于第一种实现方式,它需要使用锁定机制,而且由于C#的内存模型问题,它需要使用volatile关键字来修饰实例变量。下面是这种实现方式的实现代码:


public sealed class Singleton
{
    private static volatile Singleton instance=null;
    private static readonly object padlock=new object();
 
    private Singleton()
    {
    }
 
    public static Singleton GetInstance()
    {
        if (instance==null)
        {
            lock (padlock)
            {
                if (instance==null)
                {
                    instance=new Singleton();
                }
            }
        }
        return instance;
    }
}
    

下面是这种实现方式的性能测试代码:


class Program
{
    static void Main(string[] args)
    {
        Stopwatch sw=new Stopwatch();
 
        // 非单例调用
        sw.Start();
        for (int i=0; i < 10000000; i++)
        {
            var obj=new TestClass();
        }
        sw.Stop();
        Console.WriteLine("非单例调用:{0}毫秒", sw.ElapsedMilliseconds);
 
        // 单例调用
        sw.Reset();
        sw.Start();
        for (int i=0; i < 10000000; i++)
        {
            var obj=Singleton.GetInstance();
        }
        sw.Stop();
        Console.WriteLine("单例调用:{0}毫秒", sw.ElapsedMilliseconds);
 
        Console.ReadLine();
    }
}
 
public class TestClass
{
}
 
public sealed class Singleton
{
    private static volatile Singleton instance=null;
    private static readonly object padlock=new object();
 
    private Singleton()
    {
    }
 
    public static Singleton GetInstance()
    {
        if (instance==null)
        {
            lock (padlock)
            {
                if (instance==null)
                {
                    instance=new Singleton();
                }
            }
        }
        return instance;
    }
}
    

通过测试,我们可以发现,锁定访问的双重检查锁定实现方式花费了121毫秒,而私有构造函数 + 私有静态变量 + 静态GetInstance方法实现方式只花费了26毫秒,性能相差4倍左右。

总结

C#单例模式是非常常用的设计模式,也是一种非常高效的设计模式。在实现C#单例模式时,我们需要选择合适的实现方式。不同的实现方式会对程序的性能产生不同的影响,因此我们需要在实现C#单例模式时,考虑到程序的性能问题。

文章评论