Semaphore e SemaphoreSlimSemaphore and SemaphoreSlim

La classe System.Threading.Semaphore rappresenta un semaforo denominato (systemwide) o locale.The System.Threading.Semaphore class represents a named (systemwide) or local semaphore. È un semplice wrapper per l'oggetto semaforo Win32.It is a thin wrapper around the Win32 semaphore object. I semafori Win32 sono semafori di conteggio che possono essere usati per controllare l'accesso a un pool di risorse.Win32 semaphores are counting semaphores, which can be used to control access to a pool of resources.

La classe SemaphoreSlim rappresenta un semaforo leggero e veloce che può essere usato per l'attesa in un singolo processo quando si prevedono tempi di attesa molto brevi.The SemaphoreSlim class represents a lightweight, fast semaphore that can be used for waiting within a single process when wait times are expected to be very short. SemaphoreSlim si basa quanto più possibile sulle primitive di sincronizzazione fornite da Common Language Runtime (CLR).SemaphoreSlim relies as much as possible on synchronization primitives provided by the common language runtime (CLR). Tuttavia, fornisce anche gli handle di attesa basati sul kernel e inizializzati in modo differito necessari per supportare l'attesa in più semafori.However, it also provides lazily initialized, kernel-based wait handles as necessary to support waiting on multiple semaphores. SemaphoreSlim supporta anche l'utilizzo di token di annullamento, ma non supporta i semafori denominati né l'utilizzo di un handle di attesa per la sincronizzazione.SemaphoreSlim also supports the use of cancellation tokens, but it does not support named semaphores or the use of a wait handle for synchronization.

Gestione di una risorsa limitataManaging a Limited Resource

I thread entrano nel semaforo chiamando il metodo WaitOne, che viene ereditato dalla classe WaitHandle, nel caso di un oggetto System.Threading.Semaphore, oppure il metodo SemaphoreSlim.Wait o SemaphoreSlim.WaitAsync, nel caso di un oggetto SemaphoreSlim.Threads enter the semaphore by calling the WaitOne method, which is inherited from the WaitHandle class, in the case of a System.Threading.Semaphore object, or the SemaphoreSlim.Wait or SemaphoreSlim.WaitAsync method, in the case of a SemaphoreSlim object. Al termine della chiamata, il conteggio del semaforo viene decrementato.When the call returns, the count on the semaphore is decremented. Quando un thread richiede accesso e il conteggio è zero, il thread si blocca.When a thread requests entry and the count is zero, the thread blocks. Quando i thread rilasciano il semaforo chiamando il metodo Semaphore.Release o SemaphoreSlim.Release, i thread bloccati potranno entrare.As threads release the semaphore by calling the Semaphore.Release or SemaphoreSlim.Release method, blocked threads are allowed to enter. Per i thread bloccati al semaforo non esiste alcun ordine garantito, ad esempio first-in, first-out (FIFO) o last-in, first-out (LIFO).There is no guaranteed order, such as first-in, first-out (FIFO) or last-in, first-out (LIFO), for blocked threads to enter the semaphore.

Un thread può entrare nel semaforo più volte chiamando il metodo System.Threading.Semaphore dell'oggetto WaitOne oppure il metodo SemaphoreSlim dell'oggetto Wait ripetutamente.A thread can enter the semaphore multiple times by calling the System.Threading.Semaphore object's WaitOne method or the SemaphoreSlim object's Wait method repeatedly. Per rilasciare il semaforo, il thread può chiamare l'overload del metodo Semaphore.Release() o SemaphoreSlim.Release() per lo stesso numero di volte oppure chiamare l'overload del metodo Semaphore.Release(Int32) o SemaphoreSlim.Release(Int32) e specificare il numero di accessi da rilasciare.To release the semaphore, the thread can either call the Semaphore.Release() or SemaphoreSlim.Release() method overload the same number of times, or call the Semaphore.Release(Int32) or SemaphoreSlim.Release(Int32) method overload and specify the number of entries to be released.

Semafori e identità threadSemaphores and Thread Identity

I due tipi di semaforo non applicano l'identità thread alle chiamate ai metodi WaitOne, Wait, Release e SemaphoreSlim.Release.The two semaphore types do not enforce thread identity on calls to the WaitOne, Wait, Release, and SemaphoreSlim.Release methods. Ad esempio, uno scenario di utilizzo comune per i semafori implica un thread producer e un thread consumer, di cui uno incrementa sempre il conteggio del semaforo e l'altro lo decrementa sempre.For example, a common usage scenario for semaphores involves a producer thread and a consumer thread, with one thread always incrementing the semaphore count and the other always decrementing it.

È compito del programmatore garantire che un thread non rilasci il semaforo troppe volte.It is the programmer's responsibility to ensure that a thread does not release the semaphore too many times. Ad esempio, si consideri un semaforo con un conteggio massimo di due e il thread A e B accedano entrambi al semaforo.For example, suppose a semaphore has a maximum count of two, and that thread A and thread B both enter the semaphore. Se un errore di programmazione nel thread B fa sì che venga chiamato Release due volte, entrambe le chiamate hanno esito positivo.If a programming error in thread B causes it to call Release twice, both calls succeed. Il conteggio sul semaforo è completo e quando il thread A alla fine chiama Release, viene generata un'eccezione SemaphoreFullException.The count on the semaphore is full, and when thread A eventually calls Release, a SemaphoreFullException is thrown.

Semafori denominatiNamed Semaphores

Il sistema operativo Windows consente di assegnare nomi ai semafori.The Windows operating system allows semaphores to have names. Un semaforo denominato è a livello di sistema:A named semaphore is system wide. vale a dire che, una volta creato, il semaforo denominato è visibile a tutti i thread in tutti i processi.That is, once the named semaphore is created, it is visible to all threads in all processes. In questo modo, il semaforo denominato può essere usato per sincronizzare le attività di processi e thread.Thus, named semaphore can be used to synchronize the activities of processes as well as threads.

È possibile creare un oggetto Semaphore che rappresenta un semaforo di sistema denominato usando uno dei costruttori che specifica un nome.You can create a Semaphore object that represents a named system semaphore by using one of the constructors that specifies a name.

Nota

Poiché i semafori denominati sono a livello di sistema, è possibile avere più oggetti Semaphore che rappresentano lo stesso semaforo denominato.Because named semaphores are system wide, it is possible to have multiple Semaphore objects that represent the same named semaphore. A ogni chiamata a un costruttore o al metodo Semaphore.OpenExisting viene creato un nuovo oggetto Semaphore.Each time you call a constructor or the Semaphore.OpenExisting method, a new Semaphore object is created. Specificando lo stesso nome ripetutamente verranno creati più oggetti che rappresentano lo stesso semaforo denominato.Specifying the same name repeatedly creates multiple objects that represent the same named semaphore.

Prestare attenzione quando si usano i semafori denominati:Be careful when you use named semaphores. siccome sono a livello di sistema, un altro processo che usa lo stesso nome può accedere al semaforo in modo imprevisto.Because they are system wide, another process that uses the same name can enter your semaphore unexpectedly. Il malware in esecuzione sullo stesso computer potrebbe sfruttare questa opportunità per un attacco Denial of Service.Malicious code executing on the same computer could use this as the basis of a denial-of-service attack.

Usare il controllo degli accessi per proteggere un oggetto Semaphore che rappresenta un semaforo denominato, preferibilmente usando un costruttore che specifichi un oggetto System.Security.AccessControl.SemaphoreSecurity.Use access control security to protect a Semaphore object that represents a named semaphore, preferably by using a constructor that specifies a System.Security.AccessControl.SemaphoreSecurity object. È anche possibile applicare la sicurezza del controllo degli accessi usando il metodo Semaphore.SetAccessControl, ma in tal modo verrà creata una finestra di vulnerabilità tra l'ora di creazione del semaforo e l'ora in cui viene protetto.You can also apply access control security using the Semaphore.SetAccessControl method, but this leaves a window of vulnerability between the time the semaphore is created and the time it is protected. La protezione dei semafori con la sicurezza del controllo degli accessi aiuta a impedire gli attacchi dannosi, ma non risolve il problema dei conflitti di nomi non intenzionali.Protecting semaphores with access control security helps prevent malicious attacks, but does not solve the problem of unintentional name collisions.

Vedere ancheSee also