10

我目前正在編寫一個C#應用程序。我是使用ConcurrentDictionary的新手,因此對其線程安全性有一些疑問。首先,這是我的詞典:一些關於使用ConcurrentDictionary的問題

/// <summary> 
    /// A dictionary of all the tasks scheduled 
    /// </summary> 
    private ConcurrentDictionary<string, ITask> tasks; 

我實例化這個在我的課,並用它來跟蹤我的所有對象實現ITask的。我想確保我的設置能夠在多線程環境中正常工作。

如果多個線程想要獲得ConcurrentDictionary中項目數的計數,是否需要鎖定它?

如果我想從字典中獲取特定的密鑰,請獲取該密鑰的對象並調用其上的方法,是否需要鎖定它?例如:

/// <summary> 
    /// Runs a specific task. 
    /// </summary> 
    /// <param name="name">Task name.</param> 
    public void Run(string name) 
    { 
     lock (this.syncObject) 
     { 
      var task = this.tasks[name] as ITask; 
      if (task != null) 
      { 
       task.Execute(); 
      } 
     } 
    } 

記住多個線程可以調用Run方法來調用ITask的Execute方法。我的目標是讓所有的線程安全並且儘可能保持高性能。

回答

9

的方法和ConcurrentDictionary的性質自理完全線程安全的:

http://msdn.microsoft.com/en-us/library/dd287191.aspx

表示鍵值對,可以是通過 多個線程同時訪問的線程安全集合。

這包括Count屬性:

計數快照語義,代表了此刻的 ConcurrentDictionary項目的數量時,計數 訪問。

然而這樣做意味着字典裏舉行的對象本身是線程安全的。也就是說,沒有任何東西阻止兩個線程訪問相同的對象並嘗試運行其上的Execute方法。如果您想序列化(鎖定)訪問每個單獨的任務爲Execute方法,那麼我建議有一個鎖定對象內部Task和鎖定運行時Execute

public class Task 
{ 
    private object _locker = new object(); 

    public void Execute() 
    { 
     lock (_locker) { 
      // code here 
     } 
    } 
} 

這保證了至少每一個人任務沒有按沒有多個線程運行Execute。我猜這是你從問題的上下文以及類和方法的名字中得到的結果。

+0

是'.count'屬性線程安全嗎?或'.Count()'方法?有什麼不同? – Zapnologica

2

ConcurrentDictionary的所有方法都可以安全地從多個線程中調用。

它不能保證程序的其他部分不需要同步,因爲您可能需要使用鎖來同時訪問其他對象/多個對象。

I.e.您的示例代碼在獲取任務並執行時鎖定。它顯示了一個鎖定以自動訪問多個對象的示例。

備註:您應該檢查您的鎖task.Execute(),因爲它禁止其他線程並行執行任務。這可能是你想要達到的目標,但是在這種情況下,使用ConcurrentDictionary可能會矯枉過正。