多线程c#应用中的惰性单例模式

本文关键字:单例模式 应用 多线程 | 更新日期: 2023-09-27 18:02:12

我正在开发一个多线程c#应用程序,它正在使用WCF web服务。到web服务的连接将有一个我们可以定义的特定超时,在此之后它将关闭。我希望使用单例类存储到web服务的连接。我试图得到实例如下:

CLazySingleton ins = CLazySingleton.Instance;
string connection = CLazySingleton.abc;
下面是单例类的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LazySingleton
{
    public class CLazySingleton
    {
        private static readonly Lazy<CLazySingleton> _instance
            = new Lazy<CLazySingleton>(() => new CLazySingleton());
        private static readonly object ThreadLock = new object();
        public static string abc;  
        //I will use the service connection object in place of 'abc' in the application
        //assume that 'abc' is storing the connection object    
        private CLazySingleton()
        { }
        public static CLazySingleton Instance
        {
            get
            {   
                if (abc == null)
                {
                    lock (ThreadLock)
                    {
                        //Make the connection
                        abc = "Connection stored in this variable";
                        Console.WriteLine("Connection Made successfully");
                        return _instance.Value;
                    }                    
                }
                else
                {
                    return _instance.Value;
                }
            }
        }
    }
}

我的问题是:1. 这段代码能够照顾多个线程试图获得实例在同一时间?这是我目前最担心的问题。2. 我能有更好的解决办法吗?3.我是否需要在这里使用'lock'或使用Lazy方法来处理多线程试图获得实例?

如有任何帮助,不胜感激。

谢谢!

多线程c#应用中的惰性单例模式

根据微软的延迟初始化文档,在标题为"线程安全初始化"的章节下:

默认情况下,Lazy对象是线程安全的。

考虑到这一点,您的abc字段不必是静态的。当您使用Lazy<T>实例化您的单例时,在CLazySingleton构造函数中初始化您的连接是安全的。

这段代码能够照顾多个线程试图同时获得实例吗?

在您的场景中,

可以是初始化两次的"abc"字段。想象一下这种情况,"abc"变量为空。在赋值之前,第一个线程将在"lock"块中。第二个线程将在锁之前等待。因此,第一个线程将初始化"abc",第二个线程将重新初始化它(您检查null是在锁定之外,这就是原因)。但也许这不是你应该害怕的事情。

我有更好的解决方案吗?

是的,你可以。让我在这个答案的最后部分描述一下。

我是否需要在这里使用'lock'或使用Lazy方法来处理多线程试图获得实例?

在Lazy类中创建Value属性是线程安全的。在您的场景中,我将使用Lazy<>类的IsValueCreated属性的优势。您还需要ThreadLock对象。还有一件事是,一旦您访问Lazy<>类的Value属性,IsValueCreated属性将返回true(这就是技巧;-))
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LazySingleton
{
    public class CLazySingleton
    {
        private static readonly Lazy<CLazySingleton> _instance
            = new Lazy<CLazySingleton>(() => new CLazySingleton());
        private static readonly object ThreadLock = new object();
        public static string abc;  
        //I will use the service connection object in place of 'abc' in the application
        //assume that 'abc' is storing the connection object    
        private CLazySingleton()
        { }
        public static CLazySingleton Instance
        {
            get
            {   
                if (_instance.IsValueCreated)
                {
                    return _instance.Value;
                }
                lock (ThreadLock)
                {
                    if (abc == null)
                    {
                        abc = "Connection stored in this variable";
                        Console.WriteLine("Connection Made successfully");
                    }
                }
                return _instance.Value;
            }
        }
    }
}

简单使用ThreadSafetyMode

 Lazy<MergeSort> ty = new Lazy<MergeSort>(LazyThreadSafetyMode.ExecutionAndPublication);