Condividi tramite


Semaphore e SemaphoreSlim

La classe System.Threading.Semaphore rappresenta un semaforo locale o denominato (a livello di sistema). È un thin wrapper per l'oggetto semaforo Win32. I semafori Win32 sono semafori di conteggio utilizzabili per controllare l'accesso a un pool di risorse.

La classe SemaphoreSlim rappresenta un semaforo semplice e veloce che può essere utilizzato per l'attesa in un singolo processo quando si prevedono tempi di attesa molto brevi. SemaphoreSlim si basa quanto più possibile sulle primitive di sincronizzazione fornite da Common Language Runtime (CLR). Tuttavia, fornisce anche secondo necessità handle di attesa basati sul kernel e inizializzati in modalità differita, per supportare l'attesa in più semafori. SemaphoreSlim supporta inoltre l'utilizzo di token di annullamento, ma non supporta i semafori denominati né l'utilizzo di un handle di attesa per la sincronizzazione.

Gestione di una risorsa limitata

Per accedere al semaforo i thread chiamano il metodo WaitOne ereditato dalla classe WaitHandle. Quando la chiamata viene restituita, il conteggio del semaforo subisce una diminuzione. Quando un thread richiede di accedere e il conteggio è uguale a zero, il thread si blocca. Non appena i thread rilasciano il semaforo chiamando il metodo Semaphore.Release, ai thread bloccati è consentito l'accesso. Non esiste alcun ordine garantito, ad esempio First In First Out (FIFO) o Last In First Out (LIFO), per l'accesso dei thread bloccati al semaforo.

Un thread può accedere al semaforo più volte chiamando ripetutamente il metodo WaitOne. Per rilasciare il semaforo, il thread può chiamare l'overload del metodo Release() lo stesso numero di volte, oppure chiamare l'overload del metodo Release(Int32) e specificare il numero di voci da rilasciare.

Semafori e identità dei thread

La classe Semaphore non impone l'identità dei thread sulle chiamate ai metodi WaitOne e Release. Si supponga uno scenario di utilizzo comune dei semafori in cui siano presenti un thread producer e un thread consumer con il conteggio del semaforo rispettivamente in continuo aumento e in continua diminuzione.

È responsabilità del programmatore garantire che un thread non rilasci il semaforo un numero eccessivo di volte. Si supponga ad esempio che un semaforo presenti un conteggio massimo di due e che i thread A e B accedano entrambi al semaforo. Se un errore di programmazione nel thread B fa sì che venga chiamato due volte Release, entrambe le chiamate avranno esito positivo. Il conteggio del semaforo è completo e quando il thread A chiamerà Release, verrà generata una SemaphoreFullException.

Semafori denominati

Il sistema operativo Windows consente la denominazione dei semafori. Un semaforo denominato è valido a livello di sistema, ovvero, dopo essere stato creato, è visibile a tutti i thread in tutti i processi. I semafori denominati possono essere pertanto utilizzati per sincronizzare le attività dei processi, nonché dei thread.

È possibile creare un oggetto Semaphore che rappresenti un semaforo di sistema denominato utilizzando uno dei costruttori che specifica un nome.

NotaNota

Poiché i semafori denominati sono validi a livello di sistema, è possibile che più oggetti Semaphore rappresentino lo stesso semaforo denominato.Ogni qualvolta si chiama un costruttore o il metodo Semaphore.OpenExisting, viene creato un nuovo oggetto Semaphore.Specificando lo stesso nome ripetutamente vengono creati più oggetti che rappresentano lo stesso semaforo denominato.

Prestare particolare attenzione quando si utilizzano i semafori denominati. Dal momento che sono validi a livello di sistema, un altro processo che utilizza lo stesso nome può accedere al semaforo in modo imprevisto. È possibile che il malware in esecuzione sullo stesso computer si serva di questa situazione come base per un attacco di tipo Denial of Service.

Utilizzare la sicurezza del controllo di accesso per proteggere un oggetto Semaphore che rappresenta un semaforo denominato, possibilmente mediante un costruttore che specifica un oggetto System.Security.AccessControl.SemaphoreSecurity. È inoltre possibile applicare questo tipo di sicurezza utilizzando il metodo Semaphore.SetAccessControl. Tuttavia, questo sistema lascia un margine di vulnerabilità tra il momento in cui viene creato il semaforo e il momento in cui viene applicata la sicurezza. L'applicazione della sicurezza del controllo di accesso ai semafori impedisce gli attacchi dannosi ma non risolve il problema dei conflitti di nomi non intenzionali.

Vedere anche

Riferimenti

Semaphore

SemaphoreSlim

Altre risorse

Oggetti e funzionalità del threading