2017-04-14 49 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附近加鎖 - 這絕不會發生。

因此,簡而言之,如果您沒有正確地同步訪問線程安全結構,即使是讀取,也可能會出現可怕的錯誤。而且你甚至可能沒有注意到這一點,並且將很難調試這些問題,因爲應用程序可能表現得像一切都很好。

相關問題