Mutex Classe
Definizione
Importante
Alcune informazioni sono relative alla release non definitiva del prodotto, che potrebbe subire modifiche significative prima della release definitiva. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Primitiva di sincronizzazione che può essere usata anche per la sincronizzazione interprocesso.
public ref class Mutex sealed : System::Threading::WaitHandle
public sealed class Mutex : System.Threading.WaitHandle
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class Mutex : System.Threading.WaitHandle
type Mutex = class
inherit WaitHandle
[<System.Runtime.InteropServices.ComVisible(true)>]
type Mutex = class
inherit WaitHandle
Public NotInheritable Class Mutex
Inherits WaitHandle
- Ereditarietà
- Ereditarietà
- Attributi
Esempio
In questo esempio viene illustrato come viene usato un oggetto locale Mutex per sincronizzare l'accesso a una risorsa protetta. Poiché ogni thread chiamante viene bloccato fino a quando non acquisisce la proprietà del mutex, deve chiamare il metodo per rilasciare la ReleaseMutex proprietà del mutex.
using System;
using System.Threading;
class Example
{
// Create a new Mutex. The creating thread does not own the mutex.
private static Mutex mut = new Mutex();
private const int numIterations = 1;
private const int numThreads = 3;
static void Main()
{
// Create the threads that will use the protected resource.
for(int i = 0; i < numThreads; i++)
{
Thread newThread = new Thread(new ThreadStart(ThreadProc));
newThread.Name = String.Format("Thread{0}", i + 1);
newThread.Start();
}
// The main thread exits, but the application continues to
// run until all foreground threads have exited.
}
private static void ThreadProc()
{
for(int i = 0; i < numIterations; i++)
{
UseResource();
}
}
// This method represents a resource that must be synchronized
// so that only one thread at a time can enter.
private static void UseResource()
{
// Wait until it is safe to enter.
Console.WriteLine("{0} is requesting the mutex",
Thread.CurrentThread.Name);
mut.WaitOne();
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name);
// Place code to access non-reentrant resources here.
// Simulate some work.
Thread.Sleep(500);
Console.WriteLine("{0} is leaving the protected area",
Thread.CurrentThread.Name);
// Release the Mutex.
mut.ReleaseMutex();
Console.WriteLine("{0} has released the mutex",
Thread.CurrentThread.Name);
}
}
// The example displays output like the following:
// Thread1 is requesting the mutex
// Thread2 is requesting the mutex
// Thread1 has entered the protected area
// Thread3 is requesting the mutex
// Thread1 is leaving the protected area
// Thread1 has released the mutex
// Thread3 has entered the protected area
// Thread3 is leaving the protected area
// Thread3 has released the mutex
// Thread2 has entered the protected area
// Thread2 is leaving the protected area
// Thread2 has released the mutex
Imports System.Threading
Module Example
' Create a new Mutex. The creating thread does not own the mutex.
Private mut As New Mutex()
Private Const numIterations As Integer = 1
Private Const numThreads As Integer = 3
Public Sub Main()
' Create the threads that will use the protected resource.
For i As Integer = 0 To numThreads - 1
Dim newThread As New Thread(AddressOf ThreadProc)
newThread.Name = String.Format("Thread{0}", i + 1)
newThread.Start()
Next
' The main thread exits, but the application continues to
' run until all foreground threads have exited.
End Sub
Private Sub ThreadProc()
For i As Integer = 0 To numIterations - 1
UseResource()
Next
End Sub
' This method represents a resource that must be synchronized
' so that only one thread at a time can enter.
Private Sub UseResource()
' Wait until it is safe to enter.
Console.WriteLine("{0} is requesting the mutex",
Thread.CurrentThread.Name)
mut.WaitOne()
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name)
' Place code to access non-reentrant resources here.
' Simulate some work.
Thread.Sleep(500)
Console.WriteLine("{0} is leaving the protected area",
Thread.CurrentThread.Name)
' Release the Mutex.
mut.ReleaseMutex()
Console.WriteLine("{0} has released the mutex",
Thread.CurrentThread.Name)
End Sub
End Module
' The example displays output like the following:
' Thread1 is requesting the mutex
' Thread2 is requesting the mutex
' Thread1 has entered the protected area
' Thread3 is requesting the mutex
' Thread1 is leaving the protected area
' Thread1 has released the mutex
' Thread3 has entered the protected area
' Thread3 is leaving the protected area
' Thread3 has released the mutex
' Thread2 has entered the protected area
' Thread2 is leaving the protected area
' Thread2 has released the mutex
Nell'esempio seguente ogni thread chiama il WaitOne(Int32) metodo per acquisire il mutex. Se l'intervallo di timeout scade, il metodo restituisce falsee il thread non acquisisce il mutex né ottiene l'accesso alla risorsa che il mutex protegge. Il ReleaseMutex metodo viene chiamato solo dal thread che acquisisce il mutex.
using System;
using System.Threading;
class Example
{
// Create a new Mutex. The creating thread does not own the mutex.
private static Mutex mut = new Mutex();
private const int numIterations = 1;
private const int numThreads = 3;
static void Main()
{
Example ex = new Example();
ex.StartThreads();
}
private void StartThreads()
{
// Create the threads that will use the protected resource.
for(int i = 0; i < numThreads; i++)
{
Thread newThread = new Thread(new ThreadStart(ThreadProc));
newThread.Name = String.Format("Thread{0}", i + 1);
newThread.Start();
}
// The main thread returns to Main and exits, but the application continues to
// run until all foreground threads have exited.
}
private static void ThreadProc()
{
for(int i = 0; i < numIterations; i++)
{
UseResource();
}
}
// This method represents a resource that must be synchronized
// so that only one thread at a time can enter.
private static void UseResource()
{
// Wait until it is safe to enter, and do not enter if the request times out.
Console.WriteLine("{0} is requesting the mutex", Thread.CurrentThread.Name);
if (mut.WaitOne(1000)) {
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name);
// Place code to access non-reentrant resources here.
// Simulate some work.
Thread.Sleep(5000);
Console.WriteLine("{0} is leaving the protected area",
Thread.CurrentThread.Name);
// Release the Mutex.
mut.ReleaseMutex();
Console.WriteLine("{0} has released the mutex",
Thread.CurrentThread.Name);
}
else {
Console.WriteLine("{0} will not acquire the mutex",
Thread.CurrentThread.Name);
}
}
~Example()
{
mut.Dispose();
}
}
// The example displays output like the following:
// Thread1 is requesting the mutex
// Thread1 has entered the protected area
// Thread2 is requesting the mutex
// Thread3 is requesting the mutex
// Thread2 will not acquire the mutex
// Thread3 will not acquire the mutex
// Thread1 is leaving the protected area
// Thread1 has released the mutex
Imports System.Threading
Class Example
' Create a new Mutex. The creating thread does not own the mutex.
Private mut As New Mutex()
Private Const numIterations As Integer = 1
Private Const numThreads As Integer = 3
Public Shared Sub Main()
Dim ex As New Example()
ex.StartThreads()
End Sub
Private Sub StartThreads()
' Create the threads that will use the protected resource.
For i As Integer = 0 To numThreads - 1
Dim newThread As New Thread(AddressOf ThreadProc)
newThread.Name = String.Format("Thread{0}", i + 1)
newThread.Start()
Next
' The main thread returns to Main and exits, but the application continues to
' run until all foreground threads have exited.
End Sub
Private Sub ThreadProc()
For i As Integer = 0 To numIterations - 1
UseResource()
Next
End Sub
' This method represents a resource that must be synchronized
' so that only one thread at a time can enter.
Private Sub UseResource()
' Wait until it is safe to enter.
Console.WriteLine("{0} is requesting the mutex",
Thread.CurrentThread.Name)
If mut.WaitOne(1000) Then
Console.WriteLine("{0} has entered the protected area",
Thread.CurrentThread.Name)
' Place code to access non-reentrant resources here.
' Simulate some work.
Thread.Sleep(5000)
Console.WriteLine("{0} is leaving the protected area",
Thread.CurrentThread.Name)
' Release the Mutex.
mut.ReleaseMutex()
Console.WriteLine("{0} has released the mutex",
Thread.CurrentThread.Name)
Else
Console.WriteLine("{0} will not acquire the mutex",
Thread.CurrentThread.Name)
End If
End Sub
Protected Overrides Sub Finalize()
mut.Dispose()
End Sub
End Class
' The example displays output like the following:
' Thread1 is requesting the mutex
' Thread1 has entered the protected area
' Thread2 is requesting the mutex
' Thread3 is requesting the mutex
' Thread2 will not acquire the mutex
' Thread3 will not acquire the mutex
' Thread1 is leaving the protected area
' Thread1 has released the mutex
Commenti
Quando due o più thread devono accedere contemporaneamente a una risorsa condivisa, il sistema deve disporre di un meccanismo di sincronizzazione per garantire che solo un thread alla volta usi la risorsa. Mutex è una primitiva di sincronizzazione che concede l'accesso esclusivo alla risorsa condivisa a un solo thread. Se un thread acquisisce un mutex, il secondo thread che vuole acquisire tale mutex viene sospeso fino a quando il primo thread non rilascia il mutex.
Importante
Questo tipo implementa l'interfaccia IDisposable . Al termine dell'uso del tipo, è necessario eliminarlo direttamente o indirettamente. Per eliminare direttamente il tipo, chiamare il Dispose relativo metodo in un try/catch blocco. Per eliminarlo indirettamente, usare un costrutto del linguaggio, ad using esempio (in C#) o Using (in Visual Basic). Per altre informazioni, vedere la sezione "Uso di un oggetto che implementa IDisposable" nell'argomento relativo all'interfaccia IDisposable .
È possibile usare il metodo per richiedere la WaitHandle.WaitOne proprietà di un mutex. Il thread chiamante si blocca fino a quando non si verifica una delle operazioni seguenti:
Il mutex viene segnalato per indicare che non è di proprietà. In questo caso, il WaitOne metodo restituisce
truee il thread chiamante assume la proprietà del mutex e accede alla risorsa protetta dal mutex. Al termine dell'accesso alla risorsa, il thread deve chiamare il metodo per rilasciare la ReleaseMutex proprietà del mutex. Il primo esempio della sezione Esempi illustra questo modello.Intervallo di timeout specificato nella chiamata a un WaitOne metodo con un
millisecondsTimeoutparametro otimeouttrascorso. In questo caso, il WaitOne metodo restituiscefalsee il thread chiamante non tenta di acquisire la proprietà del mutex. In questo caso, è necessario strutturare il codice in modo che l'accesso alla risorsa protetta dal mutex venga negato al thread chiamante. Poiché il thread non ha mai acquisito la proprietà del mutex, non deve chiamare il ReleaseMutex metodo . Il secondo esempio nella sezione Esempi illustra questo modello.
La Mutex classe applica l'identità del thread, quindi un mutex può essere rilasciato solo dal thread che lo ha acquisito. Al contrario, la classe non applica l'identità Semaphore del thread. È anche possibile passare un mutex attraverso i limiti del dominio applicazione.
Il thread proprietario di un mutex può richiedere lo stesso mutex nelle chiamate ripetute a WaitOne senza bloccarne l'esecuzione. Tuttavia, il thread deve chiamare il ReleaseMutex metodo lo stesso numero di volte per rilasciare la proprietà del mutex.
Poiché la Mutex classe eredita da WaitHandle, è anche possibile chiamare i metodi e WaitHandle.WaitAny statici WaitHandle.WaitAll per sincronizzare l'accesso a una risorsa protetta.
Se un thread termina mentre è proprietario di un mutex, il mutex viene detto essere abbandonato. Lo stato del mutex è impostato su segnalato e il thread in attesa successivo ottiene la proprietà. A partire dalla versione 2.0 di .NET Framework, viene generata una AbandonedMutexException nel thread successivo che acquisisce il mutex abbandonato. Prima della versione 2.0 di .NET Framework, non è stata generata alcuna eccezione.
Caution
Un mutex abbandonato spesso indica un errore grave nel codice. Quando un thread viene chiuso senza rilasciare il mutex, le strutture di dati protette dal mutex potrebbero non trovarsi in uno stato coerente. Il thread successivo per richiedere la proprietà del mutex può gestire questa eccezione e procedere, se è possibile verificare l'integrità delle strutture di dati.
Nel caso di un mutex a livello di sistema, un mutex abbandonato potrebbe indicare che un'applicazione è stata terminata bruscamente (ad esempio, usando Gestione attività di Windows).
I mutex sono di due tipi: mutex locali, senza nome, e mutex di sistema denominati. Un mutex locale esiste solo all'interno del tuo processo. Può essere usato da qualsiasi thread del processo che ha un riferimento all'oggetto Mutex che rappresenta il mutex. Ogni oggetto senza Mutex nome rappresenta un mutex locale separato.
I mutex di sistema denominati sono visibili in tutto il sistema operativo e possono essere usati per sincronizzare le attività dei processi. È possibile creare un Mutex oggetto che rappresenta un mutex di sistema denominato usando un costruttore che accetta un nome. L'oggetto del sistema operativo può essere creato contemporaneamente oppure può esistere prima della creazione dell'oggetto Mutex . È possibile creare più Mutex oggetti che rappresentano lo stesso mutex di sistema denominato ed è possibile usare il OpenExisting metodo per aprire un mutex di sistema denominato esistente.
Note
In un server che esegue Servizi terminal, un mutex di sistema denominato può avere due livelli di visibilità. Se il nome inizia con il prefisso Global\, il mutex è visibile in tutte le sessioni del server terminal. Se il nome inizia con il prefisso Local\, il mutex è visibile solo nella sessione del server terminal in cui è stato creato. In tal caso, un mutex separato con lo stesso nome può esistere in ognuna delle altre sessioni del server terminal nel server. Se non si specifica un prefisso quando si crea un mutex denominato, accetta il prefisso Local\. All'interno di una sessione del server terminal, due mutex i cui nomi differiscono solo per i relativi prefissi sono mutex separati ed entrambi sono visibili a tutti i processi nella sessione del server terminal. Ovvero, i nomi Global\ dei prefissi e Local\ descrivono l'ambito del nome mutex relativo alle sessioni del server terminal, non relative ai processi.
Caution
Per impostazione predefinita, un mutex denominato non è limitato all'utente che lo ha creato. Altri utenti possono essere in grado di aprire e usare il mutex, incluso l'interferimento con il mutex immettendo il mutex e non chiudendolo. Nei sistemi operativi simili a Unix, il file system viene usato nell'implementazione di mutex denominati e altri utenti possono interferire con mutex denominati in modi più significativi. In Windows, per limitare l'accesso a utenti specifici, è possibile usare un overload del costruttore o MutexAcl e passare un MutexSecurity durante la creazione del mutex denominato. Nei sistemi operativi simili a Unix, attualmente non esiste alcun modo per limitare l'accesso a un mutex denominato. Evitare di usare mutex denominati senza restrizioni di accesso nei sistemi che potrebbero avere utenti non attendibili che eseguono codice.
La barra rovesciata (\) è un carattere riservato in un nome mutex. Non usare una barra rovesciata (\) in un nome mutex, ad eccezione di quanto specificato nella nota sull'uso di mutex nelle sessioni del server terminal. In caso contrario, è possibile generare un oggetto DirectoryNotFoundException , anche se il nome del mutex rappresenta un file esistente.
Costruttori
| Nome | Descrizione |
|---|---|
| Mutex() |
Inizializza una nuova istanza della Mutex classe con le proprietà predefinite. |
| Mutex(Boolean, String, Boolean, MutexSecurity) |
Inizializza una nuova istanza della Mutex classe con un valore booleano che indica se il thread chiamante deve avere la proprietà iniziale del mutex, una stringa che è il nome del mutex, una variabile booleana che, quando il metodo restituisce, indica se al thread chiamante è stata concessa la proprietà iniziale del mutex e la sicurezza del controllo di accesso da applicare al mutex denominato. |
| Mutex(Boolean, String, Boolean) |
Inizializza una nuova istanza della Mutex classe con un valore booleano che indica se il thread chiamante deve avere la proprietà iniziale del mutex, una stringa che corrisponde al nome del mutex e un valore booleano che, quando il metodo restituisce, indica se al thread chiamante è stata concessa la proprietà iniziale del mutex. |
| Mutex(Boolean, String, NamedWaitHandleOptions, Boolean) |
Inizializza una nuova istanza della Mutex classe con un valore booleano che indica se il thread chiamante deve avere la proprietà iniziale del mutex, una stringa che corrisponde al nome del mutex, le opzioni per impostare l'ambito utente e l'accesso all'ambito sessione e un valore booleano che, quando il metodo restituisce, indica se al thread chiamante è stata concessa la proprietà iniziale del mutex. |
| Mutex(Boolean, String, NamedWaitHandleOptions) |
Inizializza una nuova istanza della Mutex classe con un valore booleano che indica se il thread chiamante deve avere la proprietà iniziale del mutex, una stringa che rappresenta il nome del mutex e le opzioni per impostare l'ambito utente e l'accesso all'ambito sessione. |
| Mutex(Boolean, String) |
Inizializza una nuova istanza della Mutex classe con un valore booleano che indica se il thread chiamante deve avere la proprietà iniziale del mutex e una stringa che corrisponde al nome del mutex. |
| Mutex(Boolean) |
Inizializza una nuova istanza della Mutex classe con un valore booleano che indica se il thread chiamante deve avere la proprietà iniziale del mutex. |
| Mutex(String, NamedWaitHandleOptions) |
Inizializza una nuova istanza della Mutex classe con una stringa che corrisponde al nome del mutex e alle opzioni per impostare l'ambito utente e l'accesso all'ambito sessione. Il thread chiamante non richiede la proprietà iniziale del mutex. |
Campi
| Nome | Descrizione |
|---|---|
| WaitTimeout |
Indica che si è verificato un timeout di un'operazione WaitAny(WaitHandle[], Int32, Boolean) prima che uno degli handle di attesa sia stato segnalato. Questo campo è costante. (Ereditato da WaitHandle) |
Proprietà
| Nome | Descrizione |
|---|---|
| Handle |
Obsoleti.
Obsoleti.
Ottiene o imposta l'handle nativo del sistema operativo. (Ereditato da WaitHandle) |
| SafeWaitHandle |
Ottiene o imposta l'handle nativo del sistema operativo. (Ereditato da WaitHandle) |
Metodi
| Nome | Descrizione |
|---|---|
| Close() |
Rilascia tutte le risorse contenute nell'oggetto corrente WaitHandle. (Ereditato da WaitHandle) |
| CreateObjRef(Type) |
Crea un oggetto che contiene tutte le informazioni pertinenti necessarie per generare un proxy utilizzato per comunicare con un oggetto remoto. (Ereditato da MarshalByRefObject) |
| Dispose() |
Rilascia tutte le risorse usate dall'istanza corrente della WaitHandle classe . (Ereditato da WaitHandle) |
| Dispose(Boolean) |
In caso di override in una classe derivata, rilascia le risorse non gestite usate da WaitHandlee, facoltativamente, rilascia le risorse gestite. (Ereditato da WaitHandle) |
| Equals(Object) |
Determina se l'oggetto specificato è uguale all'oggetto corrente. (Ereditato da Object) |
| GetAccessControl() |
Ottiene un MutexSecurity oggetto che rappresenta la sicurezza del controllo di accesso per il mutex denominato. |
| GetHashCode() |
Funge da funzione hash predefinita. (Ereditato da Object) |
| GetLifetimeService() |
Obsoleti.
Recupera l'oggetto servizio di durata corrente che controlla i criteri di durata per questa istanza. (Ereditato da MarshalByRefObject) |
| GetType() |
Ottiene il Type dell'istanza corrente. (Ereditato da Object) |
| InitializeLifetimeService() |
Obsoleti.
Ottiene un oggetto servizio di durata per controllare i criteri di durata per questa istanza. (Ereditato da MarshalByRefObject) |
| MemberwiseClone() |
Crea una copia superficiale del Objectcorrente. (Ereditato da Object) |
| MemberwiseClone(Boolean) |
Crea una copia superficiale dell'oggetto corrente MarshalByRefObject . (Ereditato da MarshalByRefObject) |
| OpenExisting(String, MutexRights) |
Apre il mutex denominato specificato, se già esistente, con l'accesso di sicurezza desiderato. |
| OpenExisting(String, NamedWaitHandleOptions) |
Apre il mutex denominato specificato, se esiste già. Se le opzioni sono impostate solo sull'utente corrente, i controlli di accesso dell'oggetto vengono verificati per l'utente chiamante. |
| OpenExisting(String) |
Apre il mutex denominato specificato, se esiste già. |
| ReleaseMutex() |
Rilascia una Mutex sola volta. |
| SetAccessControl(MutexSecurity) |
Imposta la sicurezza del controllo di accesso per un mutex di sistema denominato. |
| ToString() |
Restituisce una stringa che rappresenta l'oggetto corrente. (Ereditato da Object) |
| TryOpenExisting(String, Mutex) |
Apre il mutex denominato specificato, se esiste già, e restituisce un valore che indica se l'operazione è riuscita. |
| TryOpenExisting(String, MutexRights, Mutex) |
Apre il mutex denominato specificato, se già esistente, con l'accesso di sicurezza desiderato e restituisce un valore che indica se l'operazione è riuscita. |
| TryOpenExisting(String, NamedWaitHandleOptions, Mutex) |
Apre il mutex denominato specificato, se esiste già, e restituisce un valore che indica se l'operazione è riuscita. Se le opzioni sono impostate solo sull'utente corrente, i controlli di accesso dell'oggetto vengono verificati per l'utente chiamante. |
| WaitOne() |
Blocca il thread corrente fino a quando l'oggetto corrente WaitHandle non riceve un segnale. (Ereditato da WaitHandle) |
| WaitOne(Int32, Boolean) |
Blocca il thread corrente fino a quando l'oggetto corrente WaitHandle non riceve un segnale, utilizzando un intero con segno a 32 bit per specificare l'intervallo di tempo e specificando se uscire dal dominio di sincronizzazione prima dell'attesa. (Ereditato da WaitHandle) |
| WaitOne(Int32) |
Blocca il thread corrente fino a quando l'oggetto corrente WaitHandle non riceve un segnale, usando un intero con segno a 32 bit per specificare l'intervallo di tempo in millisecondi. (Ereditato da WaitHandle) |
| WaitOne(TimeSpan, Boolean) |
Blocca il thread corrente fino a quando l'istanza corrente non riceve un segnale, utilizzando un TimeSpan oggetto per specificare l'intervallo di tempo e specificando se uscire dal dominio di sincronizzazione prima dell'attesa. (Ereditato da WaitHandle) |
| WaitOne(TimeSpan) |
Blocca il thread corrente fino a quando l'istanza corrente non riceve un segnale, usando un TimeSpan oggetto per specificare l'intervallo di tempo. (Ereditato da WaitHandle) |
Implementazioni dell'interfaccia esplicita
| Nome | Descrizione |
|---|---|
| IDisposable.Dispose() |
Questa API supporta l'infrastruttura del prodotto e non è previsto che venga usata direttamente dal codice. Rilascia tutte le risorse usate da WaitHandle. (Ereditato da WaitHandle) |
Metodi di estensione
| Nome | Descrizione |
|---|---|
| GetAccessControl(Mutex) |
Restituisce i descrittori di sicurezza per l'oggetto specificato |
| GetSafeWaitHandle(WaitHandle) |
Ottiene l'handle sicuro per un handle di attesa del sistema operativo nativo. |
| SetAccessControl(Mutex, MutexSecurity) |
Imposta i descrittori di sicurezza per il mutex specificato. |
| SetSafeWaitHandle(WaitHandle, SafeWaitHandle) |
Imposta un handle sicuro per un handle di attesa del sistema operativo nativo. |
Si applica a
Thread safety
Questo tipo è thread-safe.
Vedi anche
- WaitHandle
- Thread
- di threading gestito
- Mutex