如何使这个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页面使用。所以我希望它是线程安全的和单例的。我认为在静态构造函数中初始化字典将使它只被调用一次,并且是线程安全的,不确定为什么我会不断出错。有什么想法吗?

如何使这个c类成为单例、线程安全的

我同意@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