2012-04-03 115 views
3

我有一個類(單),它包含在這個類我填充字典的實例的靜態字典字典作爲線程安全變量

private static Dictionary<string, RepositoryServiceProvider> repositoryServices = null; 

(可以從多個線程發生)。起初我只是

 RepositoryServiceProvider service = null; 
     repositoryServices.TryGetValue(this.Server.Name, out service); 
     if (service == null) { 
      service = new RepositoryServiceProvider(this.Server); 
      repositoryServices.Add(this.Server.Name, service); 
     } 

然後我得到了一些異常的項目已經添加,所以我把它改爲:

 RepositoryServiceProvider service = null;  
     repositoryServices.TryGetValue(this.Server.Name, out service); 
     if (service == null) { 
      lock (padlock) { 
      repositoryServices.TryGetValue(this.Server.Name, out service); 
      if (service == null) { 
       service = new RepositoryServiceProvider(this.Server); 
       repositoryServices.Add(this.Server.Name, service); 
      } 
      } 
     } 

和掛鎖是在類:

private static readonly object padlock = new object(); 

是這樣的線程安全?或其過度複雜?或者我應該使用ConcurentDictionary

+4

您更改的代碼不是線程安全的:初始'TryGetValue'也需要位於'lock'節中。但是,如果可能的話,您最好使用類似[ConcurrentDictionary '](http://msdn.microsoft.com/zh-cn/library/dd287191.aspx)的內容,如[Yahia的回答]中所述( http://stackoverflow.com/a/9993904/55847) - 它肯定會更安全,更簡單,甚至可能更快。 – LukeH 2012-04-03 13:13:25

+0

可能的重複http://stackoverflow.com/questions/9868219/dictionary-with-lock-or-concurency-dictionary/9868256#9868256 – daryal 2012-04-03 13:14:23

+0

@LukeH +1回答我的問題謝謝 – Zavael 2012-04-03 14:21:21

回答

8

如果你可以使用ConcurrentDictionary--它在幾種情況下比你的方法更快,因爲它在線程安全的情況下實現了大多數無鎖操作。

編輯 - 按評論:

「大多數操作鎖定免費」一詞是有點過於籠統......

基本上就意味着競爭減少......因此,在某些情況下,更高的效率相比,到具有一個全局鎖定的情況,即在第一個存儲區被鎖定時訪問第二個存儲區,就好像沒有來自訪問代碼的POV的鎖定一樣......儘管這意味着鎖定在該存儲區域的本地鎖定...實際上 - 世界各地的應用程序提供比全球鎖更好的性能 - 尤其是,與多核心。

+0

+1提到無鎖操作! – dasblinkenlight 2012-04-03 13:09:20

+0

您是否有使用無鎖操作的ConcurrentDictionary的參考? (我希望/認爲它不)。 – 2012-04-03 13:46:29

+3

無鎖線程安全集合是程序員相當於永久移動的。 「看不到鎖」並不意味着無鎖。 – 2012-04-03 13:47:22