如何使这个c类成为单例、线程安全的
本文关键字:单例 线程 安全 何使这 | 更新日期: 2023-09-27 18:29:39
所以我要做的是:
public static class MyClass
{
private Dictionary<string,IDisposable> dict = null;
static MyClass()
{
dict = new Dictionary<string,IDisposable>();
// i fill up the dictionary in a loop here
//
}
public static UseDictionary(string name)
{
var obj = dict[name]
obj.DoSomeAction();
}
}
static void Main(string[] args)
{
Parallel.For(0, 1000, x =>
{
// assuming 'name' does exist in the dictionary
MyClass.UseDictionary("name"); // randomly throws null reference errors
});
}
我基本上想要这个类的一个实例,它只初始化字典一次(IDisposable项是我正在打开的一个昂贵的远程连接,我只想打开它一次)
这个类将被不同的asp.net页面使用。所以我希望它是线程安全的和单例的。我认为在静态构造函数中初始化字典将使它只被调用一次,并且是线程安全的,不确定为什么我会不断出错。有什么想法吗?
我同意@Leonardo Garcia Crespo的评论。根据我在这里看到的,你只在静态构造函数中写入字典,每个应用程序域只调用一次。其他所有内容都是read,如果不修改集合,通用词典支持多个阅读器。问题可能只在于被调用的代码。它还需要线程安全。或者,您可以使用另一个关联锁的字典并锁定相应的锁,这样一次只能调用一个非线程安全实例。
public static class MyClass
{
public static Dictionary<string,SomeDisposableClass> dict = null;
public static Dictionary<string,object> locks = null;
static MyClass()
{
// populate the dictionary
locks = new Dictionary<string,object>();
foreach (var key in dict.Keys)
{
locks[key] = new object();
}
}
public static void UseDictionary( string name )
{
var obj = dict[name];
var sync = locks[name];
lock(sync)
{
obj.DoSomething();
}
}
}
您也可以使用Singleton模式,但如果您只有一个静态方法,则可能没有必要。我会注意到,对于任何使用此类的代码来说,这将是非常可怕的。
是的,我知道如果用name
的相同值调用1000次,它将是单线程的。不过,如果被调用的方法不是线程安全的,那就最好了。这样,至少可以让多个线程同时对不同的name
值进行操作,因为它们锁定了不同的对象。
以下代码应该是线程安全的,因为.NET保证静态字段初始化程序的线程安全
private static readonly Dictionary<string,IDisposable> dict =
CreateAndInitializeDictionary();
private static Dictionary<string,IDisposable> CreateAndInitializeDictionary() {
var d = new Dictionary<string,IDisposable>();
.... // here add items
return d;
}
在再次查看您的代码后,我意识到您的实现也是线程安全的。问题应该在DoSomething()
中的某个位置:)
您可以在类上使用Synchronization属性。这是我为我的一个班所做的。我之所以把这些评论包括在内,是因为它们解释了情况。
[Synchronization]
public class IprServerController : ContextBoundObject
{
// We need to worry about things like a user deleting a route at the same time that another user is starting one.
// So, instead of trying to lock appropriately throughout the class, we can lock declaratively, by using the
// Synchronization attribute and deriving from ContextBoundObject. Now only one thread can execute methods on
// this class at a time.
看这里http://www.codeproject.com/Articles/14026/Generic-Singleton-Pattern-using-Reflection-in-C
对不起,:'(通往地狱的道路充满了善意
我只想给另一个简单的选择,而不进入太多的细节
一段时间后,我也遇到了问题,我发布了多web服务,所以多单例最终创建了我自己的版本。
这真的很管用,我有大约50个内部应用程序和一些使用它的外部提供商
总结良好在对c#i中的singleton模式和不同示例进行检查后,得出了一个结论,即一个好的实现是基于内部类来创建一个instanced。这保证了对构造函数的调用一次完成,尽管singleton类是从多个线程调用的,所以只有一个实例
在vb.net中简化
Public NotInheritable Class ServiceProxySingleton
Private Sub New()
End Sub
Public Shared Function GetInstance() As ServiceProxySingleton
Return NestedSingletonService._instance
End Function
' Internal class
Class NestedSingletonService
Friend Shared ReadOnly _instance As [SingletonClass] = New [SingletonClass]()
Shared Sub New()
End Sub
End Class
End Class