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 in modo atomico un blocco e di immettere lo stato di sospensione. Possono essere usati con sezioni critiche o blocchi snelli di lettura/scrittura (SRW). Le variabili di condizione supportano operazioni che "riattivano" o "riattivano tutti" i thread in attesa. Dopo che un thread viene riattivato, 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 assegnando la costante CONDITION_VARIABLE_INIT alla variabile di struttura (per inizializzare la struttura in modo statico).
Windows Server 2003 e Windows XP: le variabili della condizione non sono supportate.
Di seguito sono riportate le funzioni delle variabili di condizione.
Funzione della variabile Condition | Descrizione |
---|---|
InitializeConditionVariable | Inizializza una variabile di condizione. |
SleepConditionVariableCS | Sospendo la variabile di condizione specificata e rilascia la sezione critica specificata come operazione atomica. |
SleepConditionVariableSRW | Sospendo la 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 pseudocodice 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 reader/writer, la funzione TestPredicate
verificherà 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 Using Condition Variables.
Le variabili di condizione sono soggette a riattivazioni spurie (quelle non associate a una riattivazione esplicita) e riattivazioni rubate (un altro thread riesce a essere eseguito prima del thread woken). Pertanto, è consigliabile ricontrollare un predicato (in genere in un mentre ciclo) dopo la restituzione di un'operazione di sospensione.
È possibile riattivare altri thread usando WakeConditionVariable o WakeAllConditionVariable all'interno o all'esterno del blocco associato alla variabile della condizione. In genere è preferibile rilasciare il blocco prima di riattivare altri thread per ridurre il numero di commutatori di contesto.
Spesso è utile usare più di una variabile di condizione con lo stesso blocco. Ad esempio, un'implementazione di un blocco reader/writer può usare una singola sezione critica, ma variabili di condizione separate per lettori e writer.
Argomenti correlati