Dela via


Villkorsvariabler

Villkorsvariabler är synkroniseringspri primitiver som gör att trådar kan vänta tills ett visst villkor inträffar. Villkorsvariabler är objekt i användarläge som inte kan delas mellan processer.

Villkorsvariabler gör det möjligt för trådar att atomiskt frigöra ett lås och ange viloläge. De kan användas med kritiska avsnitt eller SRW-lås (Slim Reader/Writer). Villkorsvariabler stöder åtgärder som "väcker en" eller "väcker alla" väntande trådar. När en tråd har väckts hämtar den det lås som släpptes när tråden gick in i viloläge.

Observera att anroparen måste allokera en CONDITION_VARIABLE struktur och initiera den genom att antingen anropa InitializeConditionVariable (för att initiera strukturen dynamiskt) eller tilldela konstanten CONDITION_VARIABLE_INIT till strukturvariabeln (för att initiera strukturen statiskt).

Windows Server 2003 och Windows XP: Villkorsvariabler stöds inte.

Följande är villkorsvariabelfunktionerna.

Villkorsvariabelfunktion Beskrivning
InitializeConditionVariable Initierar en villkorsvariabel.
SleepConditionVariableCS Viloläge för den angivna villkorsvariabeln och släpper det angivna kritiska avsnittet som en atomisk åtgärd.
SleepConditionVariableSRW Viloläge för den angivna villkorsvariabeln och släpper det angivna SRW-låset som en atomisk åtgärd.
WakeAllConditionVariable Aktiverar alla trådar som väntar på den angivna villkorsvariabeln.
WakeConditionVariable Aktiverar en enda tråd som väntar på den angivna villkorsvariabeln.

 

Följande pseudokod visar det typiska användningsmönstret för villkorsvariabler.

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
}

I en implementering av ett läsar-/skrivarlås kontrollerar till exempel funktionen TestPredicate att den aktuella låsbegäran är kompatibel med befintliga ägare. Om det är det hämtar du låset; annars kan du sova. Ett mer detaljerat exempel finns i Använda villkorsvariabler.

Villkorsvariabler utsätts för falska väckningar (de som inte är associerade med en explicit aktivering) och stulna väckningar (en annan tråd lyckas köras före den vakna tråden). Därför bör du kontrollera ett predikat igen (vanligtvis i en medan loop) efter att en viloåtgärd har returnerats.

Du kan aktivera andra trådar med WakeConditionVariable eller WakeAllConditionVariable antingen inuti eller utanför låset som är associerat med villkorsvariabeln. Det är vanligtvis bättre att frigöra låset innan andra trådar aktiveras för att minska antalet kontextväxlar.

Det är ofta praktiskt att använda mer än en villkorsvariabel med samma lås. En implementering av ett läsar-/skrivarlås kan till exempel använda ett enda kritiskt avsnitt men separata villkorsvariabler för läsare och författare.

Använda villkorsvariabler