Condividi tramite


Oggetti semafori

Un oggetto semaforo è un oggetto di sincronizzazione che gestisce 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 viene incrementato ogni volta che un thread rilascia il semaforo. Quando il conteggio raggiunge zero, non è possibile attendere che lo stato dell'oggetto semaforo venga segnalato. Lo stato di un semaforo denominato è impostato come segnalato quando il relativo conteggio è maggiore di zero e come non segnalato quando il relativo conteggio è zero.

L'oggetto semaforo è utile per controllare una risorsa condivisa che può 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 sul 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 incrementata ogni volta che viene chiusa una finestra. L'applicazione specifica l'oggetto semaforo nella chiamata a una delle funzioni di attesa prima che ogni finestra venga creata. Quando il conteggio è zero, che indica 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 deve essere né 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 funzione OpenSemaphore . Per altre informazioni sui nomi per gli oggetti mutex, evento, semaforo e timer, vedere Sincronizzazione interprocesso.

Se più di un thread è in attesa di un semaforo, viene selezionato un thread in attesa. Non presupporre un ordine FIFO (first-out) 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 è diminuito 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 è in genere impostato sul valore massimo. Il conteggio viene quindi decrementato da tale livello perché viene utilizzata la risorsa protetta. In alternativa, è possibile creare un semaforo con un conteggio iniziale di zero per bloccare l'accesso alla risorsa protetta mentre l'applicazione viene inizializzata. 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, ma 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ò decrere il conteggio di un semaforo più volte specificando ripetutamente lo stesso oggetto semaforo nelle chiamate a una qualsiasi 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 distrutto 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 verranno timeout o continueranno in modo indefinito, a seconda che sia stato specificato un valore di timeout.

Uso di oggetti Semaphore