多线程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方法来处理多线程试图获得实例?
如有任何帮助,不胜感激。
谢谢!
根据微软的延迟初始化文档,在标题为"线程安全初始化"的章节下:
考虑到这一点,您的默认情况下,Lazy对象是线程安全的。
abc
字段不必是静态的。当您使用Lazy<T>
实例化您的单例时,在CLazySingleton
构造函数中初始化您的连接是安全的。
在您的场景中,这段代码能够照顾多个线程试图同时获得实例吗?
可以是初始化两次的"abc"字段。想象一下这种情况,"abc"变量为空。在赋值之前,第一个线程将在"lock"块中。第二个线程将在锁之前等待。因此,第一个线程将初始化"abc",第二个线程将重新初始化它(您检查null是在锁定之外,这就是原因)。但也许这不是你应该害怕的事情。
我有更好的解决方案吗?
是的,你可以。让我在这个答案的最后部分描述一下。
在Lazy类中创建Value属性是线程安全的。在您的场景中,我将使用Lazy<>类的IsValueCreated属性的优势。您还需要ThreadLock对象。还有一件事是,一旦您访问Lazy<>类的Value属性,IsValueCreated属性将返回true(这就是技巧;-))我是否需要在这里使用'lock'或使用Lazy方法来处理多线程试图获得实例?
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);