Synchronisierungsdatenstrukturen

Die Concurrency Runtime stellt mehrere Datenstrukturen bereit, mit denen Sie den Zugriff auf freigegebene Daten von mehreren Threads synchronisieren können. Diese Datenstrukturen sind nützlich, wenn Sie Daten freigegeben haben, die Sie selten ändern. Ein Synchronisierungsobjekt wie beispielsweise ein kritischer Abschnitt bewirkt, dass andere Threads warten, bis die freigegebene Ressource verfügbar ist. Wenn Sie ein derartiges Objekt verwenden, um den Zugriff auf häufig verwendete Daten zu synchronisieren, können Sie daher in der Anwendung Skalierbarkeit verlieren. Die Parallel Patterns Library (PPL) stellt die Concurrency::combinable-Klasse bereit, mit der Sie eine Ressource für mehrere Threads oder Aufgaben freigeben können, ohne dass eine Synchronisierung erforderlich ist. Weitere Informationen zur combinable-Klasse finden Sie unter Parallele Container und Objekte.

Abschnitte

In diesem Thema werden folgende asynchrone Meldungsblocktypen im Detail beschrieben:

  • critical_section

  • reader_writer_lock

  • scoped_lock und scoped_lock_read

  • event

critical_section

Die Concurrency::critical_section-Klasse stellt ein kooperatives gegenseitiges Ausschlussobjekt dar, das anderen Aufgaben nachgibt, anstatt ihnen zuvorzukommen. Kritische Abschnitte sind nützlich, wenn für mehrere Threads exklusiver Lese- und Schreibzugriff auf freigegebene Daten erforderlich ist.

Die critical_section-Klasse ist nicht wiedereintretend. Die Concurrency::critical_section::lock-Methode löst eine Ausnahme des Typs Concurrency::improper_lock aus, wenn es vom Thread aufgerufen wird, der bereits die Sperre besitzt.

Methoden und Funktionen

Die folgende Tabelle enthält alle wichtigen von der critical_section-Klasse definierten Methoden.

Methode

Beschreibung

lock

Ruft den kritischen Abschnitt ab. Der aufrufende Kontext blockiert, bis er die Sperre abruft.

try_lock

Versucht, den kritischen Abschnitt abzurufen, blockiert aber nicht.

unlock

Gibt den kritischen Abschnitt frei.

[Nach oben]

reader_writer_lock

Die Concurrency::reader_writer_lock-Klasse stellt threadsichere Lese-/Schreibvorgänge für freigegebene Daten bereit. Verwenden Sie Lese-/Schreibsperren, wenn für mehrere Threads gleichzeitiger Lesezugriff auf eine freigegebene Ressource erforderlich ist, aber selten auf diese freigegebene Ressource geschrieben wird. Von dieser Klasse wird jeweils nur einem Thread Schreibzugriff auf ein Objekt gewährt.

Die reader_writer_lock-Klasse kann eine bessere Leistung als die critical_section-Klasse erzielen, weil ein critical_section-Objekt exklusiven Zugriff auf eine freigegebene Ressource erhält. So wird gleichzeitiger Lesezugriff verhindert.

Wie die critical_section-Klasse stellt die reader_writer_lock-Klasse ein kooperatives gegenseitiges Ausschlussobjekt dar, das anderen Aufgaben nachgibt anstatt ihnen zuvorzukommen.

Wenn ein Thread, der auf eine freigegebene Ressource schreiben muss, eine Lese-/Schreibsperre abruft, werden andere Threads, die ebenfalls auf die Ressource zugreifen müssen, so lange blockiert, bis der Writer die Sperre aufhebt. Die reader_writer_lock-Klasse ist ein Beispiel für eine write-preference-Sperre. Dabei handelt es sich um eine Sperre, die erst die Sperre für wartende Writer und dann die für wartende Reader aufhebt.

Wie die critical_section-Klasse ist auch die reader_writer_lock-Klasse ist nicht wiedereintretend. Die Concurrency::reader_writer_lock::lock-Methode und die Concurrency::reader_writer_lock::lock_read-Methode lösen eine Ausnahme des Typs improper_lock aus, wenn sie von einem Thread aufgerufen werden, der bereits die Sperre besitzt.

Tipp

Da die reader_writer_lock-Klasse nicht wieder eintretend ist, können Sie eine schreibgeschützte Sperre nicht auf eine Reader/Writer-Sperre aktualisieren und eine Reader/Writer-Sperre nicht in eine schreibgeschützte Sperre umwandeln. Beide Vorgänge führen zu einem nicht definierten Verhalten.

Methoden und Funktionen

Die folgende Tabelle enthält alle wichtigen von der reader_writer_lock-Klasse definierten Methoden.

Methode

Beschreibung

lock

Ruft Lese-/Schreibzugriff auf die Sperre ab.

try_lock

Versucht, Lese-/Schreibzugriff auf die Sperre abzurufen, blockiert aber nicht.

lock_read

Ruft schreibgeschützten Zugriff auf die Sperre ab.

try_lock_read

Versucht, schreibgeschützten Zugriff auf die Sperre abzurufen, blockiert aber nicht.

unlock

Hebt die Sperre auf.

[Nach oben]

scoped_lock und scoped_lock_read

Die Klassen critical_section und reader_writer_lock stellen geschachtelte Hilfsklassen bereit, die das Arbeiten mit gegenseitigen Ausschlussobjekten erleichtern. Diese Hilfsklassen werden als bewertete Sperren bezeichnet.

Die critical_section-Klasse enthält die Concurrency::critical_section::scoped_lock-Klasse. Der Konstruktor ruft den Zugriff auf das bereitgestellte critical_section-Objekt ab, und die Destruktorversionen greifen auf dieses Objekt zu. Die reader_writer_lock-Klasse enthält die Concurrency::reader_writer_lock::scoped_lock-Klasse, die critical_section::scoped_lock mit der Ausnahme ähnelt, dass sie den Schreibzugriff auf das bereitgestellte reader_writer_lock-Objekt verwaltet. Die reader_writer_lock-Klasse enthält darüber hinaus die Concurrency::reader_writer_lock::scoped_lock_read-Klasse. Diese Klasse verwaltet den Lesezugriff auf das bereitgestellte reader_writer_lock-Objekt.

Beim manuellen Arbeiten mit den Objekten critical_section und reader_writer_lock bieten bewertete Sperren mehrere Vorteile. In der Regel ordnen Sie eine bewertete Sperre auf dem Stapel zu. Eine bewertete Sperre gibt den Zugriff auf das gegenseitige Ausschlussobjekt automatisch frei, wenn es zerstört wird. Aus diesem Grund muss das zugrunde liegende Objekt nicht manuell entsperrt werden. Dies ist dann nützlich, wenn eine Funktion mehrere return-Anweisungen enthält. Durch bewertete Sperren können Sie auch leichter ausnahmesicheren Code schreiben. Wenn eine throw-Aussage bewirkt, dass der Stapel entladen wird, wird der Destruktor für eine beliebige aktive bewertete Sperre aufgerufen. Dadurch wird das gegenseitige Ausschlussobjekt stets ordnungsgemäß freigegeben.

Tipp

Wenn Sie die Klassen critical_section::scoped_lock, reader_writer_lock::scoped_lock und reader_writer_lock::scoped_lock_read verwenden, geben Sie den Zugriff auf das zugrunde liegende gegenseitige Ausschlussobjekt nicht manuell frei. Dadurch kann die Laufzeit in einen ungültigen Zustand versetzt werden.

event

Die Concurrency::event-Klasse stellt ein Synchronisierungsobjekt dar, dessen Zustand signalisiert oder nicht signalisiert sein kann. Im Gegensatz zu Synchronisierungsobjekten, z. B. kritischen Abschnitten, die den Zugriff auf freigegebene Daten schützen sollen, synchronisieren Ereignisse den Ausführungsablauf.

Die event-Klasse ist dann nützlich, wenn Arbeit von einer Aufgabe für eine andere Aufgabe verrichtet wurde. Beispielsweise könnte eine Aufgabe einer anderen Aufgabe signalisieren, dass Daten von einer Netzwerkverbindung oder einer Datei gelesen wurden.

Methoden und Funktionen

Folgende Tabelle enthält einige der wichtigen von der event-Klasse definierten Methoden.

Methode

Beschreibung

wait

Wartet, bis das Ereignis signalisiert wird.

set

Versetzt das Ereignis in den signalisierten Zustand.

reset

Versetzt das Ereignis in den nicht signalisierten Zustand.

wait_for_multiple

Wartet, bis mehrere Ereignisse signalisiert werden.

Beispiel

Ein Beispiel für die Verwendung der event-Klasse finden Sie unter Vergleich der Synchronisierungsdatenstrukturen mit der Windows-API.

[Nach oben]

Verwandte Abschnitte