2017-04-14 46 views
1

ReSharper的建议在声明,称“领域有时使用synchronized块内,有时不同步使用”包裹return dic.Contains("v1");未检查静态字典中的密钥是否存在线程安全? ReSharper的认为这是不

public class MyClass 
{ 
    private static Dictionary<string, string> _dic = new Dictionary<string, string>(); 

    protected bool V1Exist() 
    { 
     return dic.Contains("v1");    
    } 
} 

但是我不明白为什么锁示例中需要。它看起来对我来说很安全。请告知

+0

'Dictionary'通常不是线程安全的。如果您需要线程安全字典,请使用'ConcurrentDictionary'。 –

+0

字典不是线程安全的。 ConcurrentDictionaries是 –

+0

如果您从多个线程编写和读取字典 - 写入和读取都不是线程安全的 – Evk

回答

2

已知字典不是线程安全的,所以您应该同步写入和读取。但是,如果你想要的东西可以去错了具体的例子 - 考虑这个小应用程序:

static void Main(string[] args) { 
    var dict = new Dictionary<int, int>(); 
    dict.Add(0, 0); 
    new Thread(() => { 
     for (int i = 1; i < int.MaxValue; i++) { 
      lock (dict) { 
       dict.Add(i, i); 
       dict.Remove(i); 
      } 
     } 
    }).Start(); 
    new Thread(() => { 
     while (true) { 
      if (!dict.ContainsKey(0)) 
       throw new Exception("cannot happen?"); 
     } 
    }).Start(); 
    Console.ReadKey(); 
} 

我们创建字典与关键0一个条目,然后我们运行两个线程。第一个线程不断地向字典中添加和删除键,但注意它不会删除带有键0的项目。键为0的项目始终存在。

第二个线程不断检查是否有键0的项目,如果没有则抛出异常。您可能会认为这绝不会发生,因为我们从不删除项目中的键0,但事实并非如此。如果你将运行这个应用程序,它会抛出“不可能发生?”异常几乎立即。如果你在ContainsKey附近加锁 - 这绝不会发生。

因此,简而言之,如果您没有正确地同步访问线程安全结构,即使是读取,也可能会出现可怕的错误。而且你甚至可能没有注意到这一点,并且将很难调试这些问题,因为应用程序可能表现得像一切都很好。

相关问题