Datenstrukturen für die parallele Programmierung

Mit .NET Framework 4 wurden verschiedene neue Typen eingeführt, die in der parallelen Programmierung hilfreich sind, einschließlich einer Gruppe gleichzeitiger Auflistungsklassen, einfache Synchronisierungsprimitiven und Typen für eine verzögerte Initialisierung. Sie können diese Typen mit jedem Multithreadanwendungscode verwenden, einschließlich der Task Parallel Library und PLINQ.

Gleichzeitige Auflistungsklassen

Die Auflistungsklassen im System.Collections.Concurrent-Namespace ermöglichen ein threadsicheres Hinzufügen und Entfernen, bei dem Sperren nach Möglichkeit vermieden und, falls erforderlich, differenzierte Sperren verwendet werden. Im Gegensatz zu Auflistungen, die in .NET Framework 1.0 und 2.0 eingeführt wurden, ist es bei einer gleichzeitigen Auflistungsklasse nicht erforderlich, dass der Benutzercode beim Zugriff auf Elemente Sperren vornimmt. Gleichzeitige Auflistungsklassen führen im Vergleich zu Typen wie System.Collections.ArrayList und System.Collections.Generic.List<T> (mit vom Benutzer implementierten Sperren) zu einer deutlichen Leistungssteigerung in Szenarien, in denen mehrere Threads Elemente zu einer Auflistung hinzufügen bzw. Elemente daraus entfernen.

In der folgenden Tabelle sind die neuen gleichzeitigen Auflistungsklassen aufgeführt:

Typ

Beschreibung

System.Collections.Concurrent.BlockingCollection<T>

Stellt Sperr- und Begrenzungsfunktionen für threadsichere Auflistungen bereit, die System.Collections.Concurrent.IProducerConsumerCollection<T> implementieren. Producerthreads werden gesperrt, wenn keine Slots verfügbar sind oder die Auflistung voll ist. Consumerthreads werden gesperrt, wenn die Auflistung leer ist. Dieser Typ unterstützt auch einen ungesperrten Zugriff durch Consumer und Producer. BlockingCollection<T> kann als Basisklasse oder Sicherungsspeicher verwendet werden, um Sperren und Begrenzungen für eine beliebige Auflistungsklasse bereitzustellen, die IEnumerable<T> unterstützt.

System.Collections.Concurrent.ConcurrentBag<T>

Eine threadsichere Sammlungsimplementierung, die skalierbare Hinzufügungs- und Abrufvorgänge bereitstellt.

System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>

Ein gleichzeitiger und skalierbarer Wörterbuchtyp.

System.Collections.Concurrent.ConcurrentQueue<T>

Eine gleichzeitige und skalierbare FIFO-Warteschlange.

System.Collections.Concurrent.ConcurrentStack<T>

Ein gleichzeitiger und skalierbarer LIFO-Stapel.

Weitere Informationen finden Sie unter Threadsichere Auflistungen.

Synchronisierungsprimitiven

Die neuen Synchronisierungsprimitiven im System.Threading-Namespace ermöglichen eine differenzierte Parallelität und höhere Leistung, indem ressourcenintensive Sperrmechanismen vermieden werden, die in veraltetem Multithreadingcode häufig vorkommen. Für einige neue Typen, wie z. B. System.Threading.Barrier und System.Threading.CountdownEvent, gibt es in früheren Versionen von .NET Framework keine Entsprechung.

In der folgenden Tabelle werden die neuen Synchronisierungstypen aufgeführt:

Typ

Beschreibung

System.Threading.Barrier

Ermöglicht, dass mehrere Threads einen Algorithmus parallel verarbeiten. Hierzu wird ein Punkt definiert, an dem jede Aufgabe ihre Ankunft signalisieren kann und dann gesperrt wird, bis einige oder alle Aufgaben an diesem Punkt angelegt sind. Weitere Informationen finden Sie unter Barriere (.NET Framework).

System.Threading.CountdownEvent

Vereinfacht Gabelungs- und Verknüpfungsszenarios (Fork & Join), indem ein einfacher Rendezvousmechanismus bereitgestellt wird. Weitere Informationen finden Sie unter CountdownEvent.

System.Threading.ManualResetEventSlim

Eine Synchronisierungsprimitive ähnlich System.Threading.ManualResetEvent. ManualResetEventSlim ist einfacher aufgebaut, kann jedoch nur für die prozessinterne Kommunikation verwendet werden. Weitere Informationen finden Sie unter ManualResetEvent und ManualResetEventSlim.

System.Threading.SemaphoreSlim

Eine Synchronisierungsprimitive, die die Anzahl der Threads beschränkt, die gleichzeitig auf eine Ressource oder einen Ressourcenpool zugreifen können. Weitere Informationen finden Sie unter Semaphore und SemaphoreSlim.

System.Threading.SpinLock

Ein Primitive für eine gegenseitige Ausschlusssperre, durch die der Thread, der die Sperre erhalten möchte, für einen bestimmten Zeitraum in einer Schleife wartet oder rotiert, bevor er seinen Anteil erhält. In Szenarios, in denen voraussichtlich nur kurz auf eine Sperre gewartet werden muss, bietet SpinLock eine bessere Leistung als andere Arten von Sperren. Weitere Informationen finden Sie unter SpinLock.

System.Threading.SpinWait

Ein kleiner, einfacher Typ, der für einen bestimmten Zeitraum rotiert und den Thread ggf. in einen Wartezustand versetzt, wenn die Anzahl der Rotationen überschritten wurde. Weitere Informationen finden Sie unter SpinWait.

Weitere Informationen finden Sie in folgenden Themen:

Verzögerte Initialisierungsklassen

Bei einer verzögerten Initialisierung wird der Speicher für ein Objekt erst zugeordnet, wenn er benötigt wird. Die verzögerte Initialisierung kann die Leistung erhöhen, indem Objektzuordnungen gleichmäßig über der Lebensdauer eines Programms verteilt werden. Sie können die verzögerte Initialisierung für einen beliebigen benutzerdefinierten Typ aktivieren, indem Sie den Lazy<T>-Typ einschließen.

In der folgenden Tabelle werden die Typen der verzögerten Initialisierung aufgeführt:

Typ

Beschreibung

System.Lazy<T>

Stellt eine einfache, threadsichere verzögerte-Initialisierung bereit.

System.Threading.ThreadLocal<T>

Stellt pro Thread einen verzögert initialisierten Wert bereit, wobei jeder Thread die Initialisierungsfunktion verzögert aufruft.

System.Threading.LazyInitializer

Stellt statische Methoden bereit, durch die keine dedizierte Instanz mit verzögerter Initialisierung zugeordnet werden muss. Stattdessen werden Verweise verwendet, um beim Zugriff auf Ziele sicherzustellen, dass diese initialisiert wurden.

Weitere Informationen finden Sie unter Verzögerte Initialisierung.

Aggregieren von Ausnahmen

Mit dem System.AggregateException-Typ können mehrere Ausnahmen, die gleichzeitig in separaten Threads ausgelöst werden, erfasst und als eine Ausnahme an den Verbindungsthread zurückgegeben werden. Die System.Threading.Tasks.Task- und System.Threading.Tasks.Parallel-Typen und PLINQ setzen AggregateException zu diesem Zweck umfassend ein. Weitere Informationen finden Sie unter Gewusst wie: Behandeln von Ausnahmen, die von Aufgaben ausgelöst werden und Gewusst wie: Behandeln von Ausnahmen in einer PLINQ-Abfrage.

Siehe auch

Referenz

System.Collections.Concurrent

System.Threading

Konzepte

Parallele Programmierung in .NET Framework