Oggetti semafori
Un oggetto semaforo è un oggetto di sincronizzazione che mantiene un conteggio compreso tra zero e un valore massimo specificato. Il conteggio viene decrementato ogni volta che un thread completa un'attesa per l'oggetto semaforo e incrementato ogni volta che un thread rilascia il semaforo. Quando il conteggio raggiunge zero, non è possibile che altri thread attendino correttamente che lo stato dell'oggetto semaforo diventi segnalato. Lo stato di un semaforo è impostato su segnalato quando il conteggio è maggiore di zero e non firmato quando il conteggio è zero.
L'oggetto semaforo è utile per controllare una risorsa condivisa in grado di supportare un numero limitato di utenti. Funge da gate che limita il numero di thread che condividono la risorsa a un numero massimo specificato. Ad esempio, un'applicazione potrebbe inserire un limite al numero di finestre create. Usa un semaforo con un conteggio massimo uguale al limite di finestra, decrementando il conteggio ogni volta che viene creata una finestra e incrementandola ogni volta che viene chiusa una finestra. L'applicazione specifica l'oggetto semaforo nella chiamata a una delle funzioni di attesa prima della creazione di ogni finestra. Quando il conteggio è zero, a indicare che è stato raggiunto il limite di finestra, la funzione di attesa blocca l'esecuzione del codice di creazione della finestra.
Un thread usa la funzione CreateSemaphore o CreateSemaphoreEx per creare un oggetto semaforo. Il thread di creazione specifica il conteggio iniziale e il valore massimo del conteggio per l'oggetto. Il conteggio iniziale non deve essere minore di zero né maggiore del valore massimo. Il thread di creazione può anche specificare un nome per l'oggetto semaforo. I thread in altri processi possono aprire un handle a un oggetto semaforo esistente specificandone il nome in una chiamata alla funzioneOpenSemaphore. Per altre informazioni sui nomi per oggetti mutex, eventi, semafori e timer, vedere Sincronizzazione interprocesso.
Se più thread sono in attesa di un semaforo, viene selezionato un thread in attesa. Non presupporre un ordine FIFO (First-In First-In, First-Out). Gli eventi esterni, ad esempio le API in modalità kernel, possono modificare l'ordine di attesa.
Ogni volta che una delle funzioni di attesa restituisce perché lo stato di un semaforo è stato impostato su segnalato, il conteggio del semaforo viene ridotto di uno. La funzione ReleaseSemaphore aumenta il conteggio di un semaforo in base a una quantità specificata. Il conteggio non può mai essere minore di zero o maggiore del valore massimo.
Il conteggio iniziale di un semaforo viene in genere impostato sul valore massimo. Il conteggio viene quindi decrementato da tale livello quando viene utilizzata la risorsa protetta. In alternativa, è possibile creare un semaforo con un conteggio iniziale pari a zero per bloccare l'accesso alla risorsa protetta durante l'inizializzazione dell'applicazione. Dopo l'inizializzazione, è possibile usare ReleaseSemaphore per incrementare il conteggio al valore massimo.
Un thread proprietario di un oggetto mutex può attendere ripetutamente che lo stesso oggetto mutex venga segnalato senza che l'esecuzione venga bloccata. Un thread che attende ripetutamente lo stesso oggetto semaforo, tuttavia decrementa il conteggio del semaforo ogni volta che viene completata un'operazione di attesa; il thread viene bloccato quando il conteggio raggiunge lo zero. Analogamente, solo il thread proprietario di un mutex può chiamare correttamente la funzione ReleaseMutex, anche se qualsiasi thread può usare ReleaseSemaphore per aumentare il conteggio di un oggetto semaforo.
Un thread può decrementare il conteggio di un semaforo più volte specificando ripetutamente lo stesso oggetto semaforo nelle chiamate a una delle funzioni di attesa . Tuttavia, la chiamata di una delle funzioni di attesa a più oggetti con una matrice che contiene più handle dello stesso semaforo non comporta più decrementi.
Al termine dell'uso dell'oggetto semaforo, chiamare la funzione CloseHandle per chiudere l'handle. L'oggetto semaforo viene eliminato definitivamente quando l'ultimo handle è stato chiuso. La chiusura dell'handle non influisce sul conteggio dei semafori; assicurarsi quindi di chiamare ReleaseSemaphore prima di chiudere l'handle o prima che il processo venga terminato. In caso contrario, le operazioni di attesa in sospeso avranno un timeout o continueranno a tempo indefinito, a seconda che sia stato specificato un valore di timeout.
Argomenti correlati