Freigeben über


Threadsichere Sammlungen

Der System.Collections.Concurrent Namespace enthält mehrere Sammlungsklassen, die threadsicher und skalierbar sind. Mehrere Threads können elemente sicher und effizient aus diesen Auflistungen hinzufügen oder entfernen, ohne dass eine zusätzliche Synchronisierung im Benutzercode erforderlich ist. Wenn Sie neuen Code schreiben, verwenden Sie immer dann die Klassen für parallele Auflistungsvorgänge, wenn mehrere Threads gleichzeitig Schreibvorgänge in der Auflistung ausführen. Wenn Sie nur aus einer freigegebenen Sammlung lesen, verwenden Sie die Klassen im System.Collections.Generic Namensraum.

System.Collections und System.Collections.Generic

Die Auflistungsklassen im System.Collections Namespace enthalten ArrayList und Hashtable. Diese Klassen bieten eine gewisse Threadsicherheit durch die Synchronized Eigenschaft, die einen threadsicheren Wrapper um die Auflistung zurückgibt. Der Wrapper funktioniert, indem die gesamte Sammlung bei jedem Hinzufügen oder Entfernen gesperrt wird. Daher muss jeder Thread, der versucht, auf die Auflistung zuzugreifen, warten, bis er die jeweilige Sperre übernehmen kann. Dieser Prozess ist nicht skalierbar und kann erhebliche Leistungsbeeinträchtigungen für große Sammlungen verursachen. Außerdem ist das Design nicht vor Rennbedingungen geschützt. Weitere Informationen finden Sie unter "Synchronisierung in generischen Sammlungen".

Die Auflistungsklassen im System.Collections.Generic Namespace enthalten List<T> und Dictionary<TKey,TValue>. Diese Klassen bieten im Vergleich zu den System.Collections Klassen verbesserte Typsicherheit und -leistung. Die System.Collections.Generic Klassen stellen jedoch keine Threadsynchronisierung bereit. Der Benutzercode muss alle Synchronisierungen bereitstellen, wenn Elemente gleichzeitig in mehreren Threads hinzugefügt oder entfernt werden.

Es wird empfohlen, die konkurrierenden Auflistungsklassen im System.Collections.Concurrent Namespace zu verwenden, da sie die Typsicherheit und auch eine effizientere und vollständigere Thread-Sicherheit bieten.

Differenzierte Sperre und sperrenfreie Mechanismen

Einige der gleichzeitigen Sammlungstypen verwenden einfache Synchronisierungsmechanismen wie SpinLock, , SpinWait, SemaphoreSlimund CountdownEvent. Diese Synchronisierungstypen verwenden normalerweise für einen kurzen Zeitraum Verzögerungsschleifen, bevor der Thread in einen echten Wait-Zustand versetzt wird. Wenn Wartezeiten als kurz eingeschätzt werden, sind Spinvorgänge weitaus weniger rechenintensiv als Wartezustände, die einen aufwändigen Kernel-Übergang umfassen. Für Auflistungsklassen, für die Spinvorgänge verwendet werden, bedeutet diese Effizienz, dass mehrere Threads Elemente mit einer hohen Rate hinzufügen und entfernen können. Weitere Informationen zum Drehen und Blockieren finden Sie unter SpinLock und SpinWait.

Die Klassen ConcurrentQueue<T> und ConcurrentStack<T> verwenden überhaupt keine Sperren. Stattdessen verlassen sie sich auf Interlocked Operationen, um Threadsicherheit zu erreichen.

Hinweis

Da die gleichzeitigen Auflistungsklassen ICollection unterstützen, stellen sie Implementierungen für die IsSynchronized- und SyncRoot-Eigenschaften bereit, obwohl diese Eigenschaften nicht relevant sind. IsSynchronized gibt immer zurück false und SyncRoot ist immer null (Nothing in Visual Basic).

In der folgenden Tabelle sind die Sammlungstypen im System.Collections.Concurrent Namespace aufgeführt:

Typ BESCHREIBUNG
BlockingCollection<T> Stellt Begrenzungs- und Blockierungsfunktionen für jeden Typ bereit, von dem IProducerConsumerCollection<T> implementiert wird. Weitere Informationen finden Sie unter BlockingCollection Overview.
ConcurrentDictionary<TKey,TValue> Threadsichere Implementierung eines Wörterbuchs mit Schlüsselwertpaaren.
ConcurrentQueue<T> Threadsichere Implementierung einer First In, First Out (FIFO)-Warteschlange.
ConcurrentStack<T> Threadsichere Implementierung eines LIFO-Stacks (Last-In-First-Out).
ConcurrentBag<T> Threadsichere Implementierung einer ungeordneten Sammlung von Elementen.
IProducerConsumerCollection<T> Die Schnittstelle, die ein Typ implementieren muss, um in einem BlockingCollection verwendet zu werden.
Titel BESCHREIBUNG
BlockingCollection(Übersicht) Beschreibt die vom BlockingCollection<T> Typ bereitgestellte Funktionalität.
Vorgehensweise: Hinzufügen und Entfernen von Elementen in einem ConcurrentDictionary Beschreibt das Hinzufügen und Entfernen von Elementen aus einem ConcurrentDictionary<TKey,TValue>
Anleitung: Elemente einzeln zu einer BlockingCollection hinzufügen und entnehmen Beschreibt, wie Elemente einer Blockierungsauflistung hinzugefügt und daraus abgerufen werden, ohne dass der schreibgeschützte Enumerator verwendet wird.
Vorgehensweise: Hinzufügen von Begrenzungs- und Sperrfunktionen zu einer Sammlung Beschreibt, wie eine beliebige Sammlungsklasse als zugrunde liegender Speichermechanismus für eine IProducerConsumerCollection<T> Auflistung verwendet wird.
Vorgehensweise: Verwenden von ForEach zum Entfernen von Elementen in einer BlockingCollection Beschreibt, wie foreach (For Each in Visual Basic) verwendet wird, um alle Elemente in einer blockierenden Auflistung zu entfernen.
Vorgehensweise: Verwenden von Arrays mit blockierenden Auflistungen in einer Pipeline Beschreibt, wie mit mehreren Blockierungsauflistungen gleichzeitig eine Pipeline implementiert wird.
Vorgehensweise: Erstellen eines Objektpools mit ConcurrentBag Zeigt, wie Sie eine ConcurrentBag verwenden, um die Leistung in Szenarien zu optimieren, in denen Sie Objekte wiederverwenden können, anstatt ständig neue Objekte zu erstellen.

Referenz