【设计模式】单例模式

小胖脸
0

单例模式是一种常用的设计模式,它确保在整个应用程序中只有一个实例被创建,并且提供了全局访问该实例的唯一途径。在多线程环境下使用单例模式时,需要考虑线程安全性,否则可能会出现多个实例被创建的问题。

本文将介绍如何使用 .NET 6 实现单例模式,并考虑到多线程的情况。使用双重检查锁定机制确保只有一个实例被创建,同时保证线程安全性。下面是示例代码:

public class Singleton
{
    private static Singleton instance = null;
    private static readonly object objLock = new object();

    // 私有构造函数,防止类被实例化
    private Singleton() { }

    // 获取 Singleton 实例的唯一途径
    public static Singleton GetInstance()
    {
        if (instance == null) // 第一次检查,减少锁的使用频率
        {
            lock (objLock) // 加锁
            {
                if (instance == null) // 第二次检查,确保只有一个实例被创建
                {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

    // 单例的某个公共方法
    public void SomeMethod()
    {
        Console.WriteLine("Call SomeMethod of Singleton.");
    }
}

在上面的示例中,Singleton 类有一个私有构造函数,防止类被实例化。GetInstance 方法是获取 Singleton 实例的唯一途径。在方法中使用了双重检查锁定机制,确保只有一个实例被创建,并加锁以保证线程安全性。在 SomeMethod 方法中,可以编写单例的某个公共方法。

如果多个线程尝试同时访问 GetInstance 方法,lock 语句可以确保同时只有一个线程被允许进入临界区。第一次检查可以减少锁的使用频率,第二次检查可以确保只有一个实例被创建。这种方法既确保了线程安全性,又尽可能地减少了锁的使用频率,提高了性能。

下面是测试代码:

// 创建两个线程测试单例模式
Thread t1 = new Thread(() =>
{
    Singleton singleton = Singleton.GetInstance();
    Console.WriteLine(singleton.GetHashCode());
});
Thread t2 = new Thread(() =>
{
    Singleton singleton = Singleton.GetInstance();
    Console.WriteLine(singleton.GetHashCode());
});

// 启动线程并等待
t1.Start();
t2.Start();
t1.Join();
t2.Join();

在测试代码中,创建了两个线程分别获取 Singleton 实例,并输出其哈希码。如果单例模式实现正确,则两个线程输出的哈希码应该是相同的。运行测试代码,可以看到输出:

6417144
6417144

哈希码相同,单例模式实现正确。

总之,当需要在多个线程中使用单例模式时,应该考虑线程安全性。使用双重检查锁定机制可以确保只有一个实例被创建,并提高性能。通过 lock 语句确保同时只有一个线程被允许进入临界区,保证线程安全性。使用 .NET 6 实现单例模式可以方便地使用此设计模式。

标签: none

添加新评论