Freigeben über


Bedingungsvariablen

Bedingungsvariablen sind Synchronisierungsgrundtypen, mit denen Threads warten können, bis eine bestimmte Bedingung auftritt. Bedingungsvariablen sind Benutzermodusobjekte, die nicht über Prozesse hinweg freigegeben werden können.

Bedingungsvariablen ermöglichen Threads, eine Sperre atomisch freizugeben und in den Ruhezustand zu gelangen. Sie können mit kritischen Abschnitten oder schlanken Lese-/Schreibsperren (SRW) verwendet werden. Bedingungsvariablen unterstützen Vorgänge, die wartende Threads "wake one" oder "wake all" unterstützen. Nachdem ein Thread aufgewacht wurde, erhält er die Sperre erneut, die er losgelassen hat, wenn der Thread in den Ruhezustand gelangt ist.

Beachten Sie, dass der Aufrufer eine CONDITION_VARIABLE Struktur zuweisen und initialisieren muss, indem entweder InitializeConditionVariable aufgerufen wird (um die Struktur dynamisch zu initialisieren) oder die Konstante CONDITION_VARIABLE_INIT der Strukturvariablen zuzuweisen (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 auf der angegebenen Bedingungsvariable und gibt den angegebenen kritischen Abschnitt als Atomoperation frei.
SleepConditionVariableSRW- Schläft in der angegebenen Bedingungsvariable und gibt die angegebene SRW-Sperre als atome Operation 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 Lese-/Schreibsperre würde die TestPredicate-Funktion beispielsweise überprüfen, ob die aktuelle Sperranforderung mit den vorhandenen Besitzern kompatibel ist. Wenn dies der Grund ist, erwerben Sie die Sperre; andernfalls schlafe. Ein ausführlicheres Beispiel finden Sie unter Verwenden von Bedingungsvariablen.

Bedingungsvariablen unterliegen spurhaften Wakeups (denen, die keiner expliziten Aktivierung zugeordnet sind) und gestohlenen Wakeups (ein anderer Thread kann vor dem weckten Thread ausgeführt werden). Daher sollten Sie ein Prädikat (in der Regel in einem während Schleife) erneut überprüfen, nachdem ein Energiesparvorgang zurückgegeben wurde.

Sie können andere Threads mit WakeConditionVariable- oder WakeAllConditionVariable- innerhalb oder außerhalb der mit der Bedingungsvariablen verknüpften Sperre reaktivieren. Es ist in der Regel besser, die Sperre freizugeben, bevor andere Threads aktiviert werden, um die Anzahl der Kontextoptionen zu reduzieren.

Es ist häufig praktisch, mehrere Bedingungsvariablen mit derselben Sperre zu verwenden. Beispielsweise kann eine Implementierung einer Lese-/Schreibsperre einen einzelnen kritischen Abschnitt, aber separate Bedingungsvariablen für Leser und Autoren verwenden.

Verwenden von Bedingungsvariablen