Variabili di condizione

Le variabili di condizione sono primitive di sincronizzazione che consentono ai thread di attendere fino a quando non si verifica una determinata condizione. Le variabili di condizione sono oggetti in modalità utente che non possono essere condivisi tra processi.

Le variabili di condizione consentono ai thread di rilasciare atomicamente un blocco e immettere lo stato di sospensione. Possono essere usati con sezioni critiche o blocchi di lettura/writer sottile (SRW). Le variabili di condizione supportano le operazioni che "riattivano" o "riattivano tutti" i thread in attesa. Dopo che un thread viene interrotto, acquisisce nuovamente il blocco rilasciato quando il thread ha immesso lo stato di sospensione.

Si noti che il chiamante deve allocare una struttura CONDITION_VARIABLE e inizializzarla chiamando InitializeConditionVariable (per inizializzare la struttura in modo dinamico) o assegnare la costante CONDITION_VARIABLE_INIT alla variabile di struttura (per inizializzare la struttura in modo statico).

Windows Server 2003 e Windows XP: Le variabili di condizione non sono supportate.

Di seguito sono riportate le funzioni delle variabili di condizione.

Funzione variabile condizione Descrizione
InitializeConditionVariable Inizializza una variabile di condizione.
SleepConditionVariableCS Dorme nella variabile di condizione specificata e rilascia la sezione critica specificata come operazione atomica.
SleepConditionVariableSRW Dorme nella variabile di condizione specificata e rilascia il blocco SRW specificato come operazione atomica.
WakeAllConditionVariable Riattiva tutti i thread in attesa della variabile di condizione specificata.
WakeConditionVariable Riattiva un singolo thread in attesa della variabile di condizione specificata.

 

Lo pseudococo seguente illustra il modello di utilizzo tipico delle variabili di condizione.

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
}

Ad esempio, in un'implementazione di un blocco lettore/writer, la TestPredicate funzione verifica che la richiesta di blocco corrente sia compatibile con i proprietari esistenti. In caso affermativo, acquisire il blocco; in caso contrario, dormire. Per un esempio più dettagliato, vedere Uso delle variabili di condizione.

Le variabili di condizione sono soggette a riattivazioni spurie (quelle non associate a una riattivazione esplicita) e le riattivazioni rubate (un altro thread riesce a essere eseguito prima del thread woken). Pertanto, è necessario ricontrollare un predicato (in genere in un ciclo di tempo ) dopo che un'operazione di sospensione restituisce.

È possibile riattivare altri thread usando WakeConditionVariable o WakeAllConditionVariable all'interno o all'esterno del blocco associato alla variabile di condizione. In genere è meglio rilasciare il blocco prima di svegliare altri thread per ridurre il numero di commutatori di contesto.

Spesso è utile usare più variabili di condizione con lo stesso blocco. Ad esempio, un'implementazione di un blocco lettore/writer può usare una singola sezione critica, ma variabili di condizione separate per lettori e writer.

Uso di variabili di condizione