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.
Relaterade ämnen