我正在开发一个使用WCF Web服务的多线程c#应用程序。与webservice的连接将具有我们可以定义的特定超时,然后它将关闭。我希望使用singleton类存储与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方法来处理试图获取实例的多线程?
任何帮助都将不胜感激。
谢谢!
答案 0 :(得分:9)
根据微软的Lazy Initialization文档,标题为“线程安全初始化”的部分:
默认情况下,Lazy个对象是线程安全的。
考虑到这一点,您的abc
字段不一定是静态的。当您使用Lazy<T>
来实例化单例时,可以安全地在CLazySingleton
构造函数中初始化连接。
答案 1 :(得分:5)
简单使用ThreadSafetyMode
Lazy<MergeSort> ty = new Lazy<MergeSort>(LazyThreadSafetyMode.ExecutionAndPublication);
答案 2 :(得分:4)
这段代码是否能够处理多个尝试同时获取实例的线程?
在您的场景中,可以将“abc”字段初始化两次。想象一下情况,“abc”变量为null。第一个线程将在值赋值之前位于“lock”块内。第二个线程将在锁定之前等待。所以第一个线程将初始化“abc”,第二个线程将重新初始化它(你检查null是否在锁之外,这就是原因)。但也许这不是你应该害怕的事情。
我可以为此提供更好的解决方案吗?
是的,你可以。让我在这个答案的最后一个块中描述它。
我是否需要在这里使用'lock'或者使用Lazy方法来处理尝试获取实例的多线程?
在Lazy类中创建Value属性是线程安全的。在您的场景中,我将使用属性IsValueCreated of Lazy&lt;&gt;类。您仍然需要ThreadLock对象。还有一件事是,一旦您访问Lazy&lt;&gt;的Value属性class,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;
}
}
}
}