Freigeben über


Threadsichere Auflistungen

.NET Framework 4 führt den System.Collections.Concurrent-Namespace ein, der mehrere Auflistungsklassen einschließt, die sowohl threadsicher als auch skalierbar sind. Mehrere Threads können diesen Auflistungen sicher und effizient Elemente hinzufügen bzw. daraus entfernen, ohne dass zusätzliche Synchronisierung in Benutzercode erforderlich ist. Wenn Sie neuen Code schreiben, verwenden Sie die gleichzeitigen Auflistungsklassen, wenn von der Auflistung gleichzeitig Elemente in mehrere Threads geschrieben werden. Wenn Sie nur von einer freigegebenen Auflistung lesen, können Sie die Klassen im System.Collections.Generic-Namespace verwenden. Es wird empfohlen, keine 1.0-Auflistungsklassen zu verwenden, sofern als Zielversion nicht .NET Framework 1.1 oder eine frühere Laufzeit festgelegt wird.

Threadsynchronisierung in den Auflistungen von .NET Framework 1.0 und 2.0

Die in .NET Framework 1.0 eingeführten Auflistungen befinden sich im System.Collections-Namespace. Diese Auflistungen, die das häufig verwendete ArrayList-Objekt und das Hashtable-Objekt einschließen, bieten eine gewisse Threadsicherheit durch die Synchronized-Eigenschaft, von der ein threadsicherer Wrapper um die Auflistung zurückgegeben wird. Der Wrapper funktioniert folgendermaßen: Die gesamte Auflistung wird bei jedem Hinzufüge- oder Entfernungsvorgang gesperrt. Daher muss jeder Thread, der versucht, auf die Auflistung zuzugreifen, warten, bis er die jeweilige Sperre übernehmen kann. Dies ist nicht skalierbar und kann beträchtliche Leistungseinbußen für große Auflistungen verursachen. Außerdem wird der Entwurf nicht völlig vor Racebedingungen geschützt. Weitere Informationen finden Sie in Synchronisierung in generischen Auflistungen auf der MSDN-Website.

Die in .NET Framework 2.0 eingeführten Auflistungsklassen befinden sich im System.Collections.Generic-Namespace. Dazu gehören List<T>, Dictionary<TKey, TValue> usw. Diese Klassen bieten verbesserte Typsicherheit und Leistung im Vergleich zu den .NET Framework 1.0-Klassen. Die .NET Framework 2.0-Auflistungsklassen stellen jedoch keine Threadsynchronisierung bereit; Benutzercode muss die gesamte Synchronisierung bereitstellen, wenn Elemente gleichzeitig in mehreren Threads hinzugefügt oder entfernt werden.

Es wird empfohlen, die gleichzeitigen Auflistungsklassen in .NET Framework 4 zu verwenden, da sie nicht nur die Typsicherheit der .NET Framework 2.0-Auflistungsklassen, sondern auch effizientere und vollständigere Threadsicherheit als die .NET Framework 1.0-Auflistungen bieten.

Differenzierte Sperre und sperrenfreie Mechanismen

Einige der gleichzeitigen Auflistungstypen verwenden einfache Synchronisierungsmechanismen z. B. SpinLock, SpinWait, SemaphoreSlim, und CountdownEvent, die neu in .NET Framework 4 sind. Diese Synchronisierungstypen verwenden normalerweise andauernde Spinvorgänge für die kurzen Zeiträume, bevor der Thread in einen echten Wartezustand versetzt wird. Wenn Wartezeiten als sehr 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 sehr hohen Rate hinzufügen und entfernen können. Weitere Informationen zu Spinvorgängen im Vergleich zu Blockierung finden Sie unter SpinLock und SpinWait.

Für die ConcurrentQueue<T>-Klasse und die ConcurrentStack<T>-Klasse werden gar keine Sperren verwendet. Stattdessen wird die Threadsicherheit durch Interlocked-Vorgänge gewährleistet.

HinweisHinweis

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

In der folgenden Tabelle sind die Auflistungstypen 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 Übersicht über BlockingCollection.

ConcurrentDictionary<TKey, TValue>

Threadsichere Implementierung eines Wörterbuchs von Schlüssel-Wert-Paaren.

ConcurrentQueue<T>

Threadsichere Implementierung einer First In, First Out (FIFO)-Warteschlange.

ConcurrentStack<T>

Threadsichere Implementierung eines Last In, First Out (LIFO)-Stapels.

ConcurrentBag<T>

Threadsichere Implementierung einer ungeordneten Auflistung von Elementen.

IProducerConsumerCollection<T>

Die Schnittstelle, die ein Typ implementieren muss, damit sie in BlockingCollection verwendet werden kann.

Verwandte Themen

Titel

Beschreibung

Übersicht über BlockingCollection

Beschreibt die vom BlockingCollection<T>-Typ bereitgestellte Funktion.

Gewusst wie: Hinzufügen und Entfernen von Elementen aus einem ConcurrentDictionary

Beschreibt, wie Elemente aus einem ConcurrentDictionary<TKey, TValue>-Objekt hinzugefügt und entfernt werden.

Gewusst wie: Hinzufügen und Entfernen von einzelnen Elementen zu bzw. aus einer BlockingCollection

Beschreibt, wie Elemente einer Blockierungsauflistung hinzugefügt und daraus abgerufen werden, ohne dass der schreibgeschützte Enumerator verwendet wird.

Gewusst wie: Hinzufügen von Begrenzungs- und Blockadefunktionen zu einer Auflistungsklasse

Beschreibt, wie jede Auflistungsklasse als zugrunde liegender Speichermechanismus für eine IProducerConsumerCollection<T>-Auflistung verwendet wird.

Gewusst wie: Entfernen von Elementen in einer BlockingCollection mit ForEach

Beschreibt, wie mit einer foreach-Anweisung (For Each in Visual Basic) alle Elemente in einer Blockierungsauflistung entfernt werden.

Gewusst wie: Verwenden von Arrays mit blockierenden Auflistungen in einer Pipeline

Beschreibt, wie mit mehreren Blockierungsauflistungen gleichzeitig eine Pipeline implementiert wird.

Gewusst wie: Erstellen eines Objektpools mittels ConcurrentBag

Zeigt die Verwendung einer parallelen Sammlung zur Verbesserung der Leistung in Szenarien, in denen Sie Objekte nicht fortlaufend neu erstellen müssen, sondern diese wiederverwenden können.

Referenz

System.Collections.Concurrent