Share via


安全執行緒集合

.NET Framework 4 引入了 System.Collections.Concurrent 命名空間,其中包括許多同時屬於安全執行緒和可擴充的集合類別。 多個執行緒可以安全且有效率地在這些集合中加入或移除項目,而不需要在使用者程式碼中使用其他同步處理。 如果您要撰寫新的程式碼,每當集合將以並行方式寫入多個執行緒時,請使用並行集合類別。 如果您只要從共用集合讀取,就可以在 System.Collections.Generic 命名空間中使用這些類別。 除非您必須以 .NET Framework 1.1 或舊版的執行階段為目標,否則我們建議您不要使用 1.0 集合類別。

.NET Framework 1.0 和 2.0 集合中的執行緒同步處理

您可以在 System.Collections 命名空間中找到 .NET Framework 1.0 所引入的集合。 這些集合 (包括常用的 ArrayListHashtable) 會透過 Synchronized 屬性提供一些執行緒安全性,以便在集合周圍傳回安全執行緒的包裝函式。 此包裝函式的運作方式是在每次加入或移除作業時鎖定整個集合。 因此,嘗試存取集合的每個執行緒都必須等候以輪流取得單一鎖定。 這項作業無法擴充,而且對於大型集合而言,可能會導致效能大幅降低。 此外,這種設計無法完全避免競爭情形。 如需詳細資訊,請參閱 MSDN 網站上的泛型集合中的同步處理 (英文)。

您可以在 System.Collections.Generic 命名空間中找到 .NET Framework 2.0 所引入的集合類別。 這些類別包括 List<T>Dictionary<TKey, TValue> 等等。 與 .NET Framework 1.0 類別相較之下,這些類別會提供改善的型別安全和效能。 不過,.NET Framework 2.0 集合類別不會提供任何執行緒同步處理。當多個執行緒以並行方式加入或移除項目時,使用者程式碼必須提供所有同步處理。

我們建議使用 .NET Framework 4 中的並行集合類別,因為它們不僅提供了 .NET Framework 2.0 集合類別的型別安全,而且它們所提供的執行緒安全性比 .NET Framework 1.0 集合更有效率且更完整。

細部鎖定和無鎖定機制

某些並行集合型別會使用輕量型同步處理機制,例如 SpinLockSpinWaitSemaphoreSlimCountdownEvent,而這些都是 .NET Framework 4 新增的機制。 這些同步處理型別通常會先暫時使用「忙碌空轉」(Busy Spinning),然後再讓執行緒進入真正的等候狀態。 當等候時間預期非常短暫時,空轉所耗費的運算資源就遠低於等候,因為等候涉及了高度耗費資源的核心轉換。 對於使用空轉的集合類別而言,這種效率表示多個執行緒可以用非常高的速率加入和移除項目。 如需空轉與 封鎖的詳細資訊,請參閱 SpinLockSpinWait

ConcurrentQueue<T>ConcurrentStack<T> 類別完全不會使用鎖定。 而是,它們會仰賴 Interlocked 作業來達成執行緒安全性。

注意事項注意事項

因為並行集合類別支援 ICollection,所以它們會提供 IsSynchronizedSyncRoot 屬性的實作,即使這些屬性無關也一樣。IsSynchronized 一定會傳回 false 而且 SyncRoot 一律為 null (Visual Basic 中的 Nothing)。

下表列出 System.Collections.Concurrent 命名空間中的集合型別。

型別

說明

BlockingCollection<T>

針對實作 IProducerConsumerCollection<T> 的任何型別提供界限和封鎖功能。 如需詳細資訊,請參閱 BlockingCollection 概觀

ConcurrentDictionary<TKey, TValue>

機碼值組之字典的安全執行緒實作。

ConcurrentQueue<T>

FIFO (先進先出) 佇列的安全執行緒實作。

ConcurrentStack<T>

LIFO (後進先出) 堆疊的安全執行緒實作。

ConcurrentBag<T>

未排序項目集合的安全執行緒實作。

IProducerConsumerCollection<T>

型別必須實作才能用於 BlockingCollection 的介面。

相關主題

標題

說明

BlockingCollection 概觀

描述 BlockingCollection<T> 型別所提供的功能。

HOW TO:在 ConcurrentDictionary 中加入和移除項目

描述如何在 ConcurrentDictionary<TKey, TValue> 中加入和移除項目。

HOW TO:從 BlockingCollection 個別加入和擷取項目

描述如何在封鎖集合中加入和擷取項目,而不使用唯讀列舉程式。

HOW TO:將界限和封鎖功能加入至集合類別

描述如何使用任何集合類別當做 IProducerConsumerCollection<T> 集合的基礎儲存機制。

HOW TO:使用 ForEach 來移除 BlockingCollection 中的項目

描述如何使用 foreach (Visual Basic 中的 For Each) 來移除封鎖集合中的所有項目。

HOW TO:在管線中使用封鎖集合的陣列

描述如何同時使用多個封鎖集合來實作管線。

HOW TO:使用 ConcurrentBag 建立物件集區

示範如何使用並行 Bag,在能夠重複使用物件而非繼續建立新物件的情況下改善效能。

參考

System.Collections.Concurrent