安全執行緒集合
.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 所引入的集合。 這些集合 (包括常用的 ArrayList 和 Hashtable) 會透過 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 集合更有效率且更完整。
細部鎖定和無鎖定機制
某些並行集合型別會使用輕量型同步處理機制,例如 SpinLock、SpinWait、SemaphoreSlim 和 CountdownEvent,而這些都是 .NET Framework 4 新增的機制。 這些同步處理型別通常會先暫時使用「忙碌空轉」(Busy Spinning),然後再讓執行緒進入真正的等候狀態。 當等候時間預期非常短暫時,空轉所耗費的運算資源就遠低於等候,因為等候涉及了高度耗費資源的核心轉換。 對於使用空轉的集合類別而言,這種效率表示多個執行緒可以用非常高的速率加入和移除項目。 如需空轉與 封鎖的詳細資訊,請參閱 SpinLock 和 SpinWait。
ConcurrentQueue<T> 和 ConcurrentStack<T> 類別完全不會使用鎖定。 而是,它們會仰賴 Interlocked 作業來達成執行緒安全性。
注意事項 |
---|
因為並行集合類別支援 ICollection,所以它們會提供 IsSynchronized 和 SyncRoot 屬性的實作,即使這些屬性無關也一樣。IsSynchronized 一定會傳回 false 而且 SyncRoot 一律為 null (Visual Basic 中的 Nothing)。 |
下表列出 System.Collections.Concurrent 命名空間中的集合型別。
型別 |
說明 |
---|---|
針對實作 IProducerConsumerCollection<T> 的任何型別提供界限和封鎖功能。 如需詳細資訊,請參閱 BlockingCollection 概觀。 |
|
機碼值組之字典的安全執行緒實作。 |
|
FIFO (先進先出) 佇列的安全執行緒實作。 |
|
LIFO (後進先出) 堆疊的安全執行緒實作。 |
|
未排序項目集合的安全執行緒實作。 |
|
型別必須實作才能用於 BlockingCollection 的介面。 |
相關主題
標題 |
說明 |
---|---|
描述 BlockingCollection<T> 型別所提供的功能。 |
|
描述如何在 ConcurrentDictionary<TKey, TValue> 中加入和移除項目。 |
|
描述如何在封鎖集合中加入和擷取項目,而不使用唯讀列舉程式。 |
|
描述如何使用任何集合類別當做 IProducerConsumerCollection<T> 集合的基礎儲存機制。 |
|
描述如何使用 foreach (Visual Basic 中的 For Each) 來移除封鎖集合中的所有項目。 |
|
描述如何同時使用多個封鎖集合來實作管線。 |
|
示範如何使用並行 Bag,在能夠重複使用物件而非繼續建立新物件的情況下改善效能。 |