Condividi tramite


Mutex Classe

Definizione

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 finché 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 né il mutex né ottiene l'accesso alla risorsa che protegge il mutex. 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 necessita di un meccanismo di sincronizzazione per garantire che un solo 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

Il tipo implementa l'interfaccia IDisposable. Dopo aver utilizzato il tipo, è necessario eliminarlo direttamente o indirettamente. Per eliminare direttamente il tipo, chiamare il metodo Dispose in un blocco try/catch. Per eliminarlo indirettamente, utilizzare un costrutto di linguaggio come ad esempio using 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 ReleaseMutex metodo per rilasciare la proprietà del mutex. Il primo esempio nella sezione Esempi illustra questo modello.

  • Intervallo di timeout specificato nella chiamata a un WaitOne metodo con un millisecondsTimeout parametro o timeout trascorso. In questo caso, il WaitOne metodo restituisce falsee il thread chiamante non tenta di acquisire ulteriormente 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, in modo che un mutex possa essere rilasciato solo dal thread che lo ha acquisito. Al contrario, la classe non applica l'identità Semaphore del thread. Un mutex può anche essere passato 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 durante la proprietà 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 un'eccezione AbandonedMutexException nel thread successivo che acquisisce il mutex abbandonato. Prima della versione 2.0 di .NET Framework, non è stata generata alcuna eccezione.

Attenzione

Un mutex abbandonato indica spesso 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 di sistema, un mutex abbandonato potrebbe indicare che un'applicazione è stata terminata in modo anomalo (ad esempio, usando Gestione attività Windows).

I mutex sono di due tipi: mutex locali, senza nome e mutex di sistema denominati. Un mutex locale esiste solo all'interno del 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ù oggetti Mutex che rappresentano lo stesso mutex di sistema denominato ed è possibile usare il metodo OpenExisting per aprire un mutex di sistema denominato esistente.

Nota

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 terminale, due mutex i cui nomi differiscono solo per i relativi prefissi sono mutex separati e entrambi sono visibili a tutti i processi nella sessione del server terminale. Ovvero, i nomi Global\ di prefisso e Local\ descrivono l'ambito del nome mutex rispetto alle sessioni del server terminale, non relative ai processi.

Attenzione

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 unix, il file system viene usato nell'implementazione di mutex denominati e altri utenti possono interferire con i mutex denominati in modi più significativi. In Windows, per limitare l'accesso a utenti specifici, è possibile usare un overload del costruttore o MutexAcl passare in un MutexSecurity oggetto durante la creazione del mutex denominato. Nei sistemi operativi unix non esiste attualmente alcun modo per limitare l'accesso a un mutex denominato. Evitare l'uso di 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 terminale. In caso contrario, potrebbe essere generata una DirectoryNotFoundException, anche se il nome del mutex rappresenta un file esistente.

Costruttori

Mutex()

Inizializza una nuova istanza della classe Mutex con le proprietà predefinite.

Mutex(Boolean)

Inizializza una nuova istanza della classe Mutex con un valore booleano che indica se il thread chiamante deve avere la proprietà iniziale del mutex.

Mutex(Boolean, String)

Inizializza una nuova istanza della classe Mutex con un valore booleano che indica se il thread chiamante deve avere la proprietà iniziale del mutex e con una stringa che rappresenta il nome del mutex.

Mutex(Boolean, String, Boolean)

Inizializza una nuova istanza della classe Mutex con un valore booleano che indica se il thread chiamante deve avere la proprietà iniziale del mutex, con una stringa che rappresenta il nome del mutex e con un valore booleano che, quando il metodo viene restituito, indichi se al thread chiamante era stata concessa la proprietà iniziale del mutex.

Mutex(Boolean, String, Boolean, MutexSecurity)

Inizializza una nuova istanza della classe Mutex con un valore booleano che indica se il thread chiamante deve avere la proprietà iniziale del mutex, con una stringa che rappresenta il nome del mutex, con una variabile Boolean che, quando il metodo viene restituito, indichi se al thread chiamante era stata concessa la proprietà iniziale del mutex e con la sicurezza del controllo di accesso da applicare al mutex denominato.

Campi

WaitTimeout

Indica che si è verificato il timeout di un'operazione WaitAny(WaitHandle[], Int32, Boolean) prima della segnalazione di uno degli handle di attesa. Questo campo è costante.

(Ereditato da WaitHandle)

Proprietà

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

Close()

Rilascia tutte le risorse contenute nell'oggetto WaitHandle corrente.

(Ereditato da WaitHandle)
CreateObjRef(Type)

Consente di creare un oggetto che contiene tutte le informazioni rilevanti necessarie per la generazione del proxy utilizzato per effettuare la comunicazione con un oggetto remoto.

(Ereditato da MarshalByRefObject)
Dispose()

Rilascia tutte le risorse usate dall'istanza corrente della classe WaitHandle.

(Ereditato da WaitHandle)
Dispose(Boolean)

Quando ne viene eseguito l'override in una classe derivata, libera le risorse non gestite usate da WaitHandle ed eventualmente di liberare le risorse gestite.

(Ereditato da WaitHandle)
Equals(Object)

Determina se l'oggetto specificato è uguale all'oggetto corrente.

(Ereditato da Object)
GetAccessControl()

Ottiene un oggetto MutexSecurity che rappresenta la sicurezza del controllo di accesso per il mutex denominato.

GetHashCode()

Funge da funzione hash predefinita.

(Ereditato da Object)
GetLifetimeService()
Obsoleti.

Consente di recuperare l'oggetto servizio di durata corrente per controllare i criteri di durata per l'istanza.

(Ereditato da MarshalByRefObject)
GetType()

Ottiene l'oggetto 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 dell'oggetto Object corrente.

(Ereditato da Object)
MemberwiseClone(Boolean)

Crea una copia dei riferimenti dell'oggetto MarshalByRefObject corrente.

(Ereditato da MarshalByRefObject)
OpenExisting(String)

Apre il mutex denominato specificato, se esistente.

OpenExisting(String, MutexRights)

Apre il mutex denominato specificato, se esistente, con l'accesso di sicurezza desiderato.

ReleaseMutex()

Rilascia l'oggetto Mutex una 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 esistente, e restituisce un valore che indica se l'operazione è stata completata.

TryOpenExisting(String, MutexRights, Mutex)

Apre il mutex denominato specificato, se esistente, con l'accesso di sicurezza desiderato, e restituisce un valore che indica se l'operazione è stata completata.

WaitOne()

Blocca il thread corrente finché l'oggetto WaitHandle corrente non riceve un segnale.

(Ereditato da WaitHandle)
WaitOne(Int32)

Blocca il thread corrente finché l'oggetto WaitHandle corrente non riceve un segnale, usando un intero con segno a 32 bit per specificare l'intervallo di tempo.

(Ereditato da WaitHandle)
WaitOne(Int32, Boolean)

Blocca il thread corrente finché l'oggetto WaitHandle corrente non riceve un segnale, usando un intero con segno a 32 bit per specificare l'intervallo di tempo e indicando se uscire dal dominio di sincronizzazione prima dell'attesa.

(Ereditato da WaitHandle)
WaitOne(TimeSpan)

Blocca il thread corrente finché l'istanza corrente non riceve un segnale, usando un valore TimeSpan per specificare l'intervallo di tempo.

(Ereditato da WaitHandle)
WaitOne(TimeSpan, Boolean)

Blocca il thread corrente finché l'istanza corrente non riceve un segnale, usando un oggetto TimeSpan per specificare l'intervallo di tempo e indicando se uscire dal dominio di sincronizzazione prima dell'attesa.

(Ereditato da WaitHandle)

Implementazioni dell'interfaccia esplicita

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

GetAccessControl(Mutex)

Restituisce i descrittori di sicurezza per l'oggetto mutex specificato.

SetAccessControl(Mutex, MutexSecurity)

Imposta i descrittori di sicurezza per il mutex specificato.

GetSafeWaitHandle(WaitHandle)

Ottiene l'handle sicuro per un handle di attesa nativo del sistema operativo.

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

Imposta un handle sicuro per un handle di attesa nativo del sistema operativo.

Si applica a

Thread safety

Questo tipo è thread-safe.

Vedi anche