共用方式為


使用安全執行緒集合的時機

.NET Framework 4 版引入了五個新的集合型別,而這些型別是特別針對支援多執行緒加入和移除作業所設計的。 為了達到執行緒安全性,這些新的型別會使用各種有效率的鎖定和無鎖定同步處理機制。 但是,同步處理會增加作業的額外負荷。 額外負荷量取決於所使用的同步處理種類、所執行的作業種類,以及其他因素,例如嘗試以並行方式存取集合的執行緒數目。

在某些案例中,同步處理額外負荷可忽略而且可讓多執行緒型別的執行速度和延展性超過其非安全執行緒對等項目 (受到外部鎖定所保護時)。 在其他案例中,額外負荷可能會導致安全執行緒型別的執行速度和延展性與此型別的外部鎖定且非安全執行緒版本相同,甚至更低。

下列各節將針對安全執行緒集合與其非安全執行緒對等項目 (在其讀取和寫入作業周圍具有使用者提供的鎖定) 的使用時機提供一般指引。 因為效能可能會根據許多因素而不同,所以指引並非特定而且不一定適用於所有情況。 如果效能非常重要,則判斷要使用哪個集合型別的最佳方式,就是根據代表性電腦組態和負載測量效能。 本文將使用下列詞彙:

  • 單純的生產者-消費者案例
    任何給定的執行緒都會加入或移除項目,但不會同時進行。

  • 混合的生產者-消費者案例
    任何給定的執行緒都會同時加入和移除項目。

  • 加速
    在相同案例中,速度較快的演算法效能相對於另一個型別而言。

  • 延展性
    與電腦上核心數目成正比的效能提升。 可延展的演算法在八個核心上執行的速度會超過在兩個核心上執行的速度。

ConcurrentQueue(T) 與Queue(T)

在單純的生產者-消費者案例中,如果每個項目的處理時間非常少 (少數指令),則 System.Collections.Concurrent.ConcurrentQueue<T> 所提供的適度效能優勢可能會超過具有外部鎖定的 System.Collections.Generic.Queue<T>。 在這個案例中,當某個專屬執行緒正排入佇列而另一個專屬執行緒正清除佇列時,ConcurrentQueue<T> 的執行效能最好。 如果您沒有強制執行此規則,在具有多個核心的電腦上,Queue<T> 的執行速度可能會稍微超過 ConcurrentQueue<T>

當處理時間大約為 500 FLOPS (浮點運算) 或以上時,雙執行緒規則就不會套用至 ConcurrentQueue<T>,因而具有非常好的延展性。 在這個案例中,Queue<T> 不會有效延展。

在混合的生產者-消費者案例中,當處理時間非常少時,具有外部鎖定之 Queue<T> 的延展性會超過 ConcurrentQueue<T>。 不過,當處理時間大約為 500 FLOPS 或以上時,ConcurrentQueue<T> 的延展性較佳。

ConcurrentStack堆疊

在單純的生產者-消費者案例中,當處理時間非常少時,則具有外部鎖定之System.Collections.Concurrent.ConcurrentStack<T>System.Collections.Generic.Stack<T> 的執行效能可能會大約與單一專屬推送執行緒和單一專屬提取執行緒相同。 不過,隨著執行緒數目增加,這兩個型別的執行速度會由於爭用增加而降低,而且 Stack<T> 的效能可能會優於 ConcurrentStack<T>。 當處理時間大約為 500 FLOPS 或以上時,這兩個型別的延展性大約相同。

在混合的生產者-消費者案例中,不論工作負載高低,ConcurrentStack<T> 的速度都比較快。

使用 PushRangeTryPopRange 可能會大幅加快存取速度。

ConcurrentDictionary 與Dictionary

一般而言,當您要以並行方式從多個執行緒加入和更新機碼或值時,請使用 System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>。 在包含經常更新和相當少讀取的案例中,ConcurrentDictionary<TKey, TValue> 通常會提供適度的優勢。 在包含許多讀取和許多更新的案例中,在具有任何核心數目的電腦上,ConcurrentDictionary<TKey, TValue> 的執行速度通常比較快。

在包含經常更新的案例中,您可以在 ConcurrentDictionary<TKey, TValue> 中提高並行程度,然後進行測量,以便查看具有更多核心的電腦效能是否提升。 如果您變更並行層級,請盡可能避免進行全域作業。

如果您只要讀取機碼或值,而且字典沒有被任何執行緒修改,Dictionary<TKey, TValue> 的速度比較快,因為不需要進行同步處理。

ConcurrentBag

在單純的生產者-消費者案例中,System.Collections.Concurrent.ConcurrentBag<T> 的執行速度可能會比其他並行集合型別更慢。

在混合的生產者-消費者案例中,不論工作負載高低,ConcurrentBag<T> 的執行速度和延展性通常會超過任何其他並行集合型別。

BlockingCollection

需要使用界限和封鎖語意時,System.Collections.Concurrent.BlockingCollection<T> 的執行速度可能會超過任何自訂實作。 它也支援豐富的取消、列舉和例外處理。

請參閱

參考

System.Collections.Concurrent

概念

安全執行緒集合

以 .NET Framework 進行平行程式設計