Mutex Classe

Definição

Um primitivo de sincronização que também pode ser usado para sincronização entre processos.

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
Herança
Herança
Atributos

Exemplos

Este exemplo mostra como um objeto local Mutex é usado para sincronizar o acesso a um recurso protegido. Como cada thread de chamada é bloqueado até adquirir a propriedade do mutex, ele deve chamar o ReleaseMutex método para liberar a propriedade do 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

No exemplo a seguir, cada thread chama o WaitOne(Int32) método para adquirir o mutex. Se o intervalo de tempo limite se esgotar, o método retornará falsee o thread não adquirirá o mutex nem obterá acesso ao recurso que o mutex protege. O ReleaseMutex método é chamado apenas pelo thread que adquire o 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

Comentários

Quando dois ou mais threads precisam acessar um recurso compartilhado ao mesmo tempo, o sistema precisa de um mecanismo de sincronização para garantir que apenas um thread de cada vez use o recurso. Mutex é um primitivo de sincronização que concede acesso exclusivo ao recurso compartilhado para apenas um thread. Se um thread adquirir um mutex, o segundo thread que deseja adquirir esse mutex será suspenso até que o primeiro thread libere o mutex.

Importante

Esse tipo implementa a IDisposable interface. Quando terminar de usar esse tipo ou objeto, você deverá descartá-lo de forma direta ou indireta. Para descartar o tipo diretamente, chame o método Dispose dele em um bloco try/catch. Para descartá-lo indiretamente, use um constructo de linguagem como using (em C#) ou Using (no Visual Basic). Para obter mais informações, consulte a seção "Usando um objeto que implementa idisposable" no tópico da IDisposable interface.

Você pode usar o WaitHandle.WaitOne método para solicitar a propriedade de um mutex. O thread de chamada bloqueia até que um destes procedimentos ocorra:

  • O mutex é sinalizado para indicar que ele não é de propriedade. Quando isso acontece, o WaitOne método retorna truee o thread de chamada assume a propriedade do mutex e acessa o recurso protegido pelo mutex. Quando terminar de acessar o recurso, o thread deverá chamar o ReleaseMutex método para liberar a propriedade do mutex. O primeiro exemplo na seção Exemplos ilustra esse padrão.

  • O intervalo de tempo limite especificado na chamada para um WaitOne método que tem um millisecondsTimeout parâmetro ou timeout decorrido. Quando isso acontece, o WaitOne método retorna falsee o thread de chamada não faz mais nenhuma tentativa de adquirir a propriedade do mutex. Nesse caso, você deve estruturar seu código para que o acesso ao recurso protegido pelo mutex seja negado ao thread de chamada. Como o thread nunca adquiriu a propriedade do mutex, ele não deve chamar o ReleaseMutex método. O segundo exemplo na seção Exemplos ilustra esse padrão.

A Mutex classe impõe a identidade do thread, de modo que um mutex só pode ser liberado pelo thread que a adquiriu. Por outro lado, a Semaphore classe não impõe a identidade do thread. Um mutex também pode ser passado entre os limites de domínio do aplicativo.

O thread que possui um mutex pode solicitar o mesmo mutex em chamadas repetidas sem WaitOne bloquear sua execução. No entanto, o thread deve chamar o ReleaseMutex método o mesmo número de vezes para liberar a propriedade do mutex.

Como a Mutex classe herda, WaitHandlevocê também pode chamar os métodos e WaitHandle.WaitAny estáticos WaitHandle.WaitAll para sincronizar o acesso a um recurso protegido.

Se um thread terminar enquanto tiver um mutex, o mutex será abandonado. O estado do mutex é definido como sinalizado e o próximo thread de espera obtém a propriedade. A partir da versão 2.0 do .NET Framework, um AbandonedMutexException é lançado no próximo thread que adquire o mutex abandonado. Antes da versão 2.0 do .NET Framework, nenhuma exceção era gerada.

Caution

Um mutex abandonado geralmente indica um erro grave no código. Quando um thread é encerrado sem liberar o mutex, as estruturas de dados protegidas pelo mutex podem não estar em um estado consistente. O próximo thread a solicitar a propriedade do mutex poderá lidar com essa exceção e continuar, se a integridade das estruturas de dados puder ser verificada.

No caso de um mutex de todo o sistema, um mutex abandonado pode indicar que um aplicativo foi finalizado abruptamente (por exemplo, usando o Gerenciador de Tarefas do Windows).

Os mutexes são de dois tipos: mutexes locais, que não têm nome e mutexes do sistema nomeados. Um mutex local existe somente dentro de seu processo. Ele pode ser usado por qualquer thread em seu processo que tenha uma referência ao Mutex objeto que representa o mutex. Cada objeto sem nome Mutex representa um mutex local separado.

Os mutexes do sistema nomeados são visíveis em todo o sistema operacional e podem ser usados para sincronizar as atividades dos processos. Você pode criar um Mutex objeto que representa um mutex do sistema nomeado usando um construtor que aceita um nome. O objeto do sistema operacional pode ser criado ao mesmo tempo ou pode existir antes da criação do Mutex objeto. Você pode criar vários objetos Mutex que representam o mesmo mutex de sistema nomeado, e você pode usar o método OpenExisting para abrir um mutex de sistema nomeado existente.

Note

Em um servidor que está executando os Serviços de Terminal, um mutex de sistema nomeado pode ter dois níveis de visibilidade. Se seu nome começar com o prefixo Global\, o mutex ficará visível em todas as sessões do servidor de terminal. Se seu nome começar com o prefixo Local\, o mutex ficará visível apenas na sessão do servidor terminal em que foi criado. Nesse caso, um mutex separado com o mesmo nome pode existir em cada uma das outras sessões de servidor de terminal no servidor. Se você não especificar um prefixo ao criar um mutex nomeado, ele usará o prefixo Local\. Em uma sessão de servidor terminal, dois mutexes cujos nomes diferem apenas por seus prefixos são mutexes separados e ambos são visíveis para todos os processos na sessão do servidor terminal. Ou seja, os nomes Global\ de prefixo e Local\ descrevem o escopo do nome mutex em relação às sessões do servidor terminal, não em relação aos processos.

Caution

Por padrão, um mutex nomeado não é restrito ao usuário que o criou. Outros usuários podem ser capazes de abrir e usar o mutex, incluindo interferir com o mutex inserindo o mutex e não saindo dele. Em sistemas operacionais semelhantes ao Unix, o sistema de arquivos é usado na implementação de mutexes nomeados e outros usuários podem interferir em mutexes nomeados de maneiras mais significativas. Em Windows, para restringir o acesso a usuários específicos, você pode usar uma sobrecarga de construtor ou MutexAcl e passar um MutexSecurity ao criar o mutex nomeado. Em sistemas operacionais semelhantes ao Unix, atualmente não há como restringir o acesso a um mutex nomeado. Evite usar mutexes nomeados sem restrições de acesso em sistemas que podem ter usuários não confiáveis executando código.

A barra invertida (\) é um caractere reservado em um nome mutex. Não use uma barra invertida (\) em um nome mutex, exceto conforme especificado na observação sobre como usar mutexes em sessões de servidor de terminal. Caso contrário, um DirectoryNotFoundException pode ser gerado, mesmo que o nome do mutex represente um arquivo existente.

Construtores

Nome Description
Mutex()

Inicializa uma nova instância da Mutex classe com propriedades padrão.

Mutex(Boolean, String, Boolean, MutexSecurity)

Inicializa uma nova instância da Mutex classe com um valor booliano que indica se o thread de chamada deve ter a propriedade inicial do mutex, uma cadeia de caracteres que é o nome do mutex, uma variável booliana que, quando o método retorna, indica se o thread de chamada recebeu a propriedade inicial do mutex e a segurança de controle de acesso a ser aplicada ao mutex nomeado.

Mutex(Boolean, String, Boolean)

Inicializa uma nova instância da Mutex classe com um valor booliano que indica se o thread de chamada deve ter a propriedade inicial do mutex, uma cadeia de caracteres que é o nome do mutex e um valor booliano que, quando o método retorna, indica se o thread de chamada recebeu a propriedade inicial do mutex.

Mutex(Boolean, String, NamedWaitHandleOptions, Boolean)

Inicializa uma nova instância da Mutex classe com um valor booliano que indica se o thread de chamada deve ter a propriedade inicial do mutex, uma cadeia de caracteres que é o nome do mutex, opções para definir o escopo do usuário e o acesso ao escopo da sessão e um valor booliano que, quando o método retorna, indica se o thread de chamada recebeu a propriedade inicial do mutex.

Mutex(Boolean, String, NamedWaitHandleOptions)

Inicializa uma nova instância da Mutex classe com um valor booliano que indica se o thread de chamada deve ter a propriedade inicial do mutex, uma cadeia de caracteres que é o nome do mutex e opções para definir o escopo do usuário e o acesso ao escopo da sessão.

Mutex(Boolean, String)

Inicializa uma nova instância da Mutex classe com um valor booliano que indica se o thread de chamada deve ter a propriedade inicial do mutex e uma cadeia de caracteres que é o nome do mutex.

Mutex(Boolean)

Inicializa uma nova instância da Mutex classe com um valor booliano que indica se o thread de chamada deve ter a propriedade inicial do mutex.

Mutex(String, NamedWaitHandleOptions)

Inicializa uma nova instância da Mutex classe com uma cadeia de caracteres que é o nome do mutex e opções para definir o escopo do usuário e o acesso ao escopo da sessão. O thread de chamada não solicita ter a propriedade inicial do mutex.

Campos

Nome Description
WaitTimeout

Indica que uma WaitAny(WaitHandle[], Int32, Boolean) operação atingiu o tempo limite antes que qualquer um dos identificadores de espera fosse sinalizado. Esse campo é constante.

(Herdado de WaitHandle)

Propriedades

Nome Description
Handle
Obsoleto.
Obsoleto.

Obtém ou define o identificador do sistema operacional nativo.

(Herdado de WaitHandle)
SafeWaitHandle

Obtém ou define o identificador do sistema operacional nativo.

(Herdado de WaitHandle)

Métodos

Nome Description
Close()

Libera todos os recursos mantidos pelo atual WaitHandle.

(Herdado de WaitHandle)
CreateObjRef(Type)

Cria um objeto que contém todas as informações relevantes necessárias para gerar um proxy usado para se comunicar com um objeto remoto.

(Herdado de MarshalByRefObject)
Dispose()

Libera todos os recursos usados pela instância atual da WaitHandle classe.

(Herdado de WaitHandle)
Dispose(Boolean)

Quando substituído em uma classe derivada, libera os recursos não gerenciados usados pelo WaitHandlee, opcionalmente, libera os recursos gerenciados.

(Herdado de WaitHandle)
Equals(Object)

Determina se o objeto especificado é igual ao objeto atual.

(Herdado de Object)
GetAccessControl()

Obtém um MutexSecurity objeto que representa a segurança do controle de acesso para o mutex nomeado.

GetHashCode()

Serve como a função de hash padrão.

(Herdado de Object)
GetLifetimeService()
Obsoleto.

Recupera o objeto de serviço de tempo de vida atual que controla a política de tempo de vida para essa instância.

(Herdado de MarshalByRefObject)
GetType()

Obtém o Type da instância atual.

(Herdado de Object)
InitializeLifetimeService()
Obsoleto.

Obtém um objeto de serviço de tempo de vida para controlar a política de tempo de vida dessa instância.

(Herdado de MarshalByRefObject)
MemberwiseClone()

Cria uma cópia superficial do Objectatual.

(Herdado de Object)
MemberwiseClone(Boolean)

Cria uma cópia superficial do objeto atual MarshalByRefObject .

(Herdado de MarshalByRefObject)
OpenExisting(String, MutexRights)

Abre o mutex nomeado especificado, se ele já existir, com o acesso de segurança desejado.

OpenExisting(String, NamedWaitHandleOptions)

Abre o mutex nomeado especificado, se ele já existir. Se as opções forem definidas apenas para o usuário atual, os controles de acesso do objeto serão verificados para o usuário que está chamando.

OpenExisting(String)

Abre o mutex nomeado especificado, se ele já existir.

ReleaseMutex()

Libera uma Mutex vez.

SetAccessControl(MutexSecurity)

Define a segurança do controle de acesso para um mutex do sistema nomeado.

ToString()

Retorna uma cadeia de caracteres que representa o objeto atual.

(Herdado de Object)
TryOpenExisting(String, Mutex)

Abre o mutex nomeado especificado, se já existir, e retorna um valor que indica se a operação foi bem-sucedida.

TryOpenExisting(String, MutexRights, Mutex)

Abre o mutex nomeado especificado, se já existir, com o acesso de segurança desejado e retorna um valor que indica se a operação foi bem-sucedida.

TryOpenExisting(String, NamedWaitHandleOptions, Mutex)

Abre o mutex nomeado especificado, se já existir, e retorna um valor que indica se a operação foi bem-sucedida. Se as opções forem definidas apenas para o usuário atual, os controles de acesso do objeto serão verificados para o usuário que está chamando.

WaitOne()

Bloqueia o thread atual até que o atual WaitHandle receba um sinal.

(Herdado de WaitHandle)
WaitOne(Int32, Boolean)

Bloqueia o thread atual até que o atual WaitHandle receba um sinal, usando um inteiro com sinal de 32 bits para especificar o intervalo de tempo e especificando se o domínio de sincronização deve ser encerrado antes da espera.

(Herdado de WaitHandle)
WaitOne(Int32)

Bloqueia o thread atual até que o atual WaitHandle receba um sinal, usando um inteiro com sinal de 32 bits para especificar o intervalo de tempo em milissegundos.

(Herdado de WaitHandle)
WaitOne(TimeSpan, Boolean)

Bloqueia o thread atual até que a instância atual receba um sinal, usando um TimeSpan para especificar o intervalo de tempo e especificando se o domínio de sincronização deve ser encerrado antes da espera.

(Herdado de WaitHandle)
WaitOne(TimeSpan)

Bloqueia o thread atual até que a instância atual receba um sinal, usando um TimeSpan para especificar o intervalo de tempo.

(Herdado de WaitHandle)

Implantações explícitas de interface

Nome Description
IDisposable.Dispose()

Esta API dá suporte à infraestrutura do produto e não deve ser usada diretamente do seu código.

Libera todos os recursos usados pelo WaitHandle.

(Herdado de WaitHandle)

Métodos de Extensão

Nome Description
GetAccessControl(Mutex)

Retorna os descritores de segurança para o especificado mutex.

GetSafeWaitHandle(WaitHandle)

Obtém o identificador seguro de um identificador de espera do sistema operacional nativo.

SetAccessControl(Mutex, MutexSecurity)

Define os descritores de segurança para o mutex especificado.

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

Define um identificador seguro para um identificador de espera do sistema operacional nativo.

Aplica-se a

Acesso thread-safe

Esse tipo é thread safe.

Confira também