Bedingungsvariablen
Bedingungsvariablen sind Synchronisierungsgrundtypen, mit denen Threads warten können, bis eine bestimmte Bedingung auftritt. Bedingungsvariablen sind Benutzermodusobjekte, die nicht prozessübergreifend freigegeben werden können.
Bedingungsvariablen ermöglichen es Threads, eine Sperre atomar freizugeben und in den Ruhezustand zu wechseln. Sie können mit kritischen Abschnitten oder SRW-Sperren (Slim Reader/Writer) verwendet werden. Bedingungsvariablen unterstützen Vorgänge, die wartende Threads "reaktivieren" oder "alle reaktivieren". Nachdem ein Thread aktiviert wurde, wird die Sperre erneut abgerufen, die er beim Eintritt des Threads in den Ruhezustand freigegeben hat.
Beachten Sie, dass der Aufrufer eine CONDITION_VARIABLE Struktur zuordnen und initialisieren muss, indem entweder InitializeConditionVariable aufgerufen wird (um die Struktur dynamisch zu initialisieren) oder die Konstante CONDITION_VARIABLE_INIT der Strukturvariablen zuweisen (um die Struktur statisch zu initialisieren).
Windows Server 2003 und Windows XP: Bedingungsvariablen werden nicht unterstützt.
Im Folgenden sind die Bedingungsvariablenfunktionen aufgeführt.
Bedingungsvariablenfunktion | BESCHREIBUNG |
---|---|
InitializeConditionVariable | Initialisiert eine Bedingungsvariable. |
SleepConditionVariableCS | Schläft für die angegebene Bedingungsvariable und gibt den angegebenen kritischen Abschnitt als atomischen Vorgang frei. |
SleepConditionVariableSRW | Schläft für die angegebene Bedingungsvariable und gibt die angegebene SRW-Sperre als atomischen Vorgang frei. |
WakeAllConditionVariable | Aktiviert alle Threads, die auf die angegebene Bedingungsvariable warten. |
WakeConditionVariable | Aktiviert einen einzelnen Thread, der auf die angegebene Bedingungsvariable wartet. |
Der folgende Pseudocode veranschaulicht das typische Verwendungsmuster von Bedingungsvariablen.
CRITICAL_SECTION CritSection;
CONDITION_VARIABLE ConditionVar;
void PerformOperationOnSharedData()
{
EnterCriticalSection(&CritSection);
// Wait until the predicate is TRUE
while( TestPredicate() == FALSE )
{
SleepConditionVariableCS(&ConditionVar, &CritSection, INFINITE);
}
// The data can be changed safely because we own the critical
// section and the predicate is TRUE
ChangeSharedData();
LeaveCriticalSection(&CritSection);
// If necessary, signal the condition variable by calling
// WakeConditionVariable or WakeAllConditionVariable so other
// threads can wake
}
Bei einer Implementierung einer Reader/Writer-Sperre überprüft die TestPredicate
Funktion beispielsweise, ob die aktuelle Sperranforderung mit den vorhandenen Besitzern kompatibel ist. Wenn dies der Grund ist, erwerben Sie die Sperre. andernfalls ruhen. Ein ausführlicheres Beispiel finden Sie unter Verwenden von Bedingungsvariablen.
Bedingungsvariablen Weckvorgängen (die nicht mit einer expliziten Aktivierung verbunden sind) und gestohlenen Aktivierungen (ein anderer Thread kann vor dem wachen Thread ausgeführt werden). Daher sollten Sie ein Prädikat (in der Regel in einer while-Schleife ) erneut überprüfen, nachdem ein Ruhezustandsvorgang zurückgegeben wird.
Sie können andere Threads mit WakeConditionVariable oder WakeAllConditionVariable aktivieren, entweder innerhalb oder außerhalb der Sperre, die der Bedingungsvariablen zugeordnet ist. Es ist in der Regel besser, die Sperre zu lösen, bevor andere Threads aktiviert werden, um die Anzahl der Kontextwechsel zu reduzieren.
Es ist oft praktisch, mehrere Bedingungsvariablen mit derselben Sperre zu verwenden. Beispielsweise kann eine Implementierung einer Reader/Writer-Sperre einen einzelnen kritischen Abschnitt verwenden, aber separate Bedingungsvariablen für Leser und Writer.
Zugehörige Themen