Delen via


Voorwaardevariabelen

Voorwaardevariabelen zijn synchronisatieprimitief die threads in staat stellen te wachten tot een bepaalde voorwaarde optreedt. Voorwaardevariabelen zijn objecten in de gebruikersmodus die niet kunnen worden gedeeld tussen processen.

Met voorwaardevariabelen kunnen threads atomisch een vergrendeling vrijgeven en de slaapstatus invoeren. Ze kunnen worden gebruikt met kritieke secties of slanke lezer/schrijver (SRW)-vergrendelingen. Voorwaardevariabelen ondersteunen bewerkingen die 'wake one' of 'wake all' wachtende threads. Nadat een draad is ontwaakt, wordt de vergrendeling opnieuw verkregen die wordt vrijgegeven wanneer de draad de slaaptoestand binnenkwam.

Houd er rekening mee dat de aanroeper een CONDITION_VARIABLE structuur moet toewijzen en deze moet initialiseren door InitializeConditionVariable aan te roepen (om de structuur dynamisch te initialiseren) of de constante CONDITION_VARIABLE_INIT toe te wijzen aan de structuurvariabele (om de structuur statisch te initialiseren).

Windows Server 2003 en Windows XP: variabelen Voorwaarde worden niet ondersteund.

Hier volgen de voorwaardevariabelefuncties.

Voorwaardevariabele, functie Beschrijving
InitializeConditionVariable- Initialiseert een voorwaardevariabele.
SleepConditionVariableCS- Slaapstanden op de opgegeven voorwaardevariabele en geeft de opgegeven kritieke sectie vrij als een atomische bewerking.
SleepConditionVariableSRW- Slaapt op de opgegeven voorwaardevariabele en geeft de opgegeven SRW-vergrendeling vrij als een atomische bewerking.
WakeAllConditionVariable- Hiermee worden alle threads geactiveerd die wachten op de opgegeven voorwaardevariabele.
WakeConditionVariable- Hiermee wordt één thread geactiveerd die wacht op de opgegeven voorwaardevariabele.

 

De volgende pseudocode demonstreert het typische gebruikspatroon van voorwaardevariabelen.

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
}

In een implementatie van een lezer/schrijververgrendeling controleert de functie TestPredicate bijvoorbeeld of de huidige vergrendelingsaanvraag compatibel is met de bestaande eigenaren. Als dat het is, verwerft u de vergrendeling; slaap anders. Zie Voorwaardevariabelen gebruikenvoor een gedetailleerder voorbeeld.

Voorwaardevariabelen zijn onderhevig aan onbedoelde ontwaakacties (die niet zijn gekoppeld aan een expliciete wake) en gestolen wakeups (een andere thread wordt uitgevoerd voordat de wakkere thread wordt geactiveerd). Daarom moet u een predicaat (meestal in een terwijl lus) opnieuw controleren nadat een slaapstandbewerking wordt geretourneerd.

U kunt andere threads wakker maken met behulp van WakeConditionVariable of WakeAllConditionVariable binnen of buiten de vergrendeling die is gekoppeld aan de voorwaardevariabele. Het is meestal beter om de vergrendeling los te laten voordat andere threads worden geactiveerd om het aantal contextswitches te verminderen.

Het is vaak handig om meer dan één voorwaardevariabele met dezelfde vergrendeling te gebruiken. Een implementatie van een lezer/schrijververgrendeling kan bijvoorbeeld één kritieke sectie gebruiken, maar afzonderlijke voorwaardevariabelen voor lezers en schrijvers.

Voorwaardevariabelen gebruiken