15

我正在开发一个使用 WCF Web 服务的多线程 c# 应用程序。与 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方法来处理试图获取实例的多线程?

任何帮助,将不胜感激。

谢谢 !

4

3 回答 3

12

根据微软的延迟初始化文档,在标题为“线程安全初始化”的部分下:

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

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

于 2013-03-05T11:44:16.910 回答
5

这段代码是否能够处理多个线程同时尝试获取实例?

在您的场景中,可以将“abc”字段初始化两次。想象一下情况,“abc”变量为空。第一个线程将在值分配之前位于“锁定”块内。第二个线程将在锁之前等待。所以第一个线程将初始化“abc”,第二个线程将重新初始化它(您对 null 的检查超出了锁定范围,这就是原因)。但也许这不是你应该害怕的事情。

我可以为此提供更好的解决方案吗?

是的你可以。让我在这个答案的最后一个块中描述它。

我需要在这里使用“锁定”还是使用 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;
            }
        }
    }
}
于 2014-08-22T10:57:53.137 回答
5

简单使用 ThreadSafetyMode

 Lazy<MergeSort> ty = new Lazy<MergeSort>(LazyThreadSafetyMode.ExecutionAndPublication);
于 2013-03-05T11:35:25.183 回答