Mutex Classe
Definição
Importante
Algumas informações dizem respeito a um produto pré-lançado que pode ser substancialmente modificado antes de ser lançado. A Microsoft não faz garantias, de forma expressa ou implícita, em relação à informação aqui apresentada.
Uma primitiva de sincronização que também pode ser usada 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 que chama é bloqueado até adquirir a propriedade do mutex, 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 seguinte, cada thread chama o WaitOne(Int32) método para adquirir o mutex. Se o intervalo de tempo expirar, o método devolve false, e o thread não adquire o mutex nem ganha acesso ao recurso que o mutex protege. O ReleaseMutex método é chamado apenas pelo fio 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
Observações
Quando dois ou mais threads precisam de aceder a um recurso partilhado ao mesmo tempo, o sistema precisa de um mecanismo de sincronização para garantir que apenas um thread de cada vez utiliza o recurso. Mutex é uma primitiva de sincronização que concede acesso exclusivo ao recurso partilhado a apenas um thread. Se um fio adquirir um mutex, o segundo fio que quer adquirir esse mutex é suspenso até que o primeiro fio liberte o mutex.
Importante
Este tipo implementa a interface IDisposable. Quando terminar de usar o tipo, você deve eliminá-lo direta ou indiretamente. Para descartar o tipo diretamente, chame seu método Dispose em um bloco try/catch. Para descartá-lo indiretamente, use uma construção de linguagem como using (em C#) ou Using (em Visual Basic). Para obter mais informações, consulte a seção "Usando um objeto que implementa IDisposable" no tópico da IDisposable interface.
Pode usar o WaitHandle.WaitOne método para pedir a posse de um mutex. O thread que chama bloqueia-se até que ocorra uma das seguintes situações:
O mutex é sinalizado para indicar que não é possuído. Quando isto acontece, o WaitOne método devolve
true, e o thread que chama assume a propriedade do mutex e acede ao recurso protegido pelo mutex. Quando termina de aceder ao recurso, o thread deve chamar o ReleaseMutex método para libertar a propriedade do mutex. O primeiro exemplo na secção de Exemplos ilustra este padrão.O intervalo de tempo especificado na chamada a um WaitOne método que tem um
millisecondsTimeouttimeoutparâmetro ou já passou. Quando isto acontece, o WaitOne método devolvefalse, e o thread que chama não faz mais tentativa de adquirir a propriedade do mutex. Neste caso, deve estruturar o seu código de forma a que o acesso ao recurso protegido pelo mutex seja negado ao thread que chama. Como o fio nunca adquiriu a propriedade do mutex, não pode chamar o ReleaseMutex método. O segundo exemplo, na secção de Exemplos, ilustra este padrão.
A Mutex classe impõe a identidade do thread, pelo que um mutex só pode ser libertado pelo thread que o adquiriu. Em contraste, a Semaphore classe não impõe a identidade do thread. Um mutex também pode ser passado através das fronteiras do domínio da aplicação.
O thread que possui um mutex pode solicitar o mesmo mutex em chamadas repetidas sem WaitOne bloquear a sua execução. No entanto, a thread deve chamar o ReleaseMutex método o mesmo número de vezes para libertar a propriedade do mutex.
Como a Mutex classe herda de WaitHandle, também pode chamar os métodos estáticos WaitHandle.WaitAllWaitHandle.WaitAny e para sincronizar o acesso a um recurso protegido.
Se um thread terminar enquanto possui um mutex, diz-se que o mutex está abandonado. O estado do mutex é definido para sinalizado, e o próximo thread em espera fica com a propriedade. A partir da versão 2.0 do .NET Framework, um AbandonedMutexException é inserido no tópico seguinte que adquire o mutex abandonado. Antes da versão 2.0 do .NET Framework, não era feita nenhuma exceção.
Atenção
Um mutex abandonado indica frequentemente um erro grave no código. Quando um thread sai sem libertar o mutex, as estruturas de dados protegidas pelo mutex podem não estar num estado consistente. O próximo tópico a solicitar a propriedade do mutex pode tratar desta exceção e prosseguir, se a integridade das estruturas de dados puder ser verificada.
No caso de um mutex a nível de sistema, um mutex abandonado pode indicar que uma aplicação foi encerrada abruptamente (por exemplo, usando o Gestor de Tarefas do Windows).
Os mutexes são de dois tipos: mutexes locais, que não têm nome, e mutexes de sistema nomeados. Um mutex local existe apenas dentro do seu processo. Pode ser usado por qualquer thread no teu 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 nomeados do sistema são visíveis em todo o sistema operativo e podem ser usados para sincronizar as atividades dos processos. Pode criar um Mutex objeto que represente um sistema nomeado mutex usando um construtor que aceita um nome. O objeto do sistema operativo pode ser criado ao mesmo tempo, ou pode existir antes da criação do Mutex objeto. Você pode criar vários Mutex objetos que representam o mesmo mutex de sistema nomeado e pode usar o método OpenExisting para abrir um mutex de sistema nomeado existente.
Note
Num servidor que executa Terminal Services, um mutex nomeado do sistema pode ter dois níveis de visibilidade. Se o seu nome começar com o prefixo Global\, o mutex é visível em todas as sessões do terminal server. Se o seu nome começar com o prefixo Local\, o mutex é visível apenas na sessão do servidor terminal onde foi criado. Nesse caso, pode existir um mutex separado com o mesmo nome em cada uma das outras sessões do terminal server no servidor. Se não especificar um prefixo ao criar um mutex nomeado, ele assume o prefixo Local\. Dentro de uma sessão de servidor de terminais, dois mutexes cujos nomes diferem apenas pelos seus prefixos são mutexes separados, e ambos são visíveis para todos os processos na sessão do servidor de terminais. Ou seja, os nomes Global\ dos prefixos e Local\ descrevem o âmbito do nome mutex relativamente às sessões do servidor terminal, não relativamente aos processos.
Atenção
Por defeito, um mutex nomeado não está restrito ao utilizador que o criou. Outros utilizadores podem conseguir abrir e usar o mutex, incluindo interferir com ele ao entrar e não sair dele. Em sistemas operativos do tipo Unix, o sistema de ficheiros é usado na implementação de mutexes nomeados, e outros utilizadores podem interferir com mutexes nomeados de formas mais significativas. No Windows, para restringir o acesso a utilizadores específicos, podes usar um constructor overload ou MutexAcl e passar um MutexSecurity ao criar o mutex nomeado. Em sistemas operativos do tipo Unix, atualmente não há forma de restringir o acesso a um mutex nomeado. Evite usar mutexes nomeados sem restrições de acesso em sistemas que possam ter utilizadores não confiáveis a executar código.
A barra inversa (\) é um carácter reservado num nome mutex. Não use uma barra diagonal (\) num nome mutex, exceto conforme especificado na nota sobre o uso de mutexes em sessões de servidor de terminal. Caso contrário, pode ser lançado a DirectoryNotFoundException , mesmo que o nome do mutex represente um ficheiro existente.
Construtores
| Name | Description |
|---|---|
| Mutex() |
Inicializa uma nova instância da Mutex classe com propriedades por defeito. |
| Mutex(Boolean, String, Boolean, MutexSecurity) |
Inicializa uma nova instância da Mutex classe com um valor Booleano que indica se a thread chamadora deve ter propriedade inicial do mutex, uma string que é o nome do mutex, uma variável Booleana que, quando o método retorna, indica se a thread chamadora recebeu a propriedade inicial do mutex e a segurança de controlo de acesso a ser aplicada ao mutex nomeado. |
| Mutex(Boolean, String, Boolean) |
Inicializa uma nova instância da Mutex classe com um valor Booleano que indica se a thread que chama deve ter a propriedade inicial do mutex, uma string que é o nome do mutex e um valor Booleano que, quando o método retorna, indica se a thread que chama recebeu a propriedade inicial do mutex. |
| Mutex(Boolean, String) |
Inicializa uma nova instância da Mutex classe com um valor Booleano que indica se o thread que chama deve ter a propriedade inicial do mutex, e uma string que é o nome do mutex. |
| Mutex(Boolean) |
Inicializa uma nova instância da Mutex classe com um valor Booleano que indica se o thread chamador deve ter a propriedade inicial do mutex. |
Campos
| Name | Description |
|---|---|
| WaitTimeout |
Indica que uma WaitAny(WaitHandle[], Int32, Boolean) operação terminou antes de qualquer uma das alças de espera ser sinalizada. Este campo é constante. (Herdado de WaitHandle) |
Propriedades
| Name | Description |
|---|---|
| Handle |
Obsoleto.
Obtém ou define o handle nativo do sistema operativo. (Herdado de WaitHandle) |
| SafeWaitHandle |
Obtém ou define o handle nativo do sistema operativo. (Herdado de WaitHandle) |
Métodos
| Name | Description |
|---|---|
| Close() |
Liberta todos os recursos detidos pelo atual WaitHandle. (Herdado de WaitHandle) |
| CreateObjRef(Type) |
Cria um objeto que contém toda a informação relevante necessária para gerar um proxy usado para comunicar com um objeto remoto. (Herdado de MarshalByRefObject) |
| Dispose() |
Liberta todos os recursos usados pela instância atual da WaitHandle classe. (Herdado de WaitHandle) |
| Dispose(Boolean) |
Quando sobreposto numa classe derivada, liberta os recursos não geridos usados pelo WaitHandle, e opcionalmente liberta os recursos geridos. (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 controlo de acesso para o mutex nomeado. |
| GetHashCode() |
Serve como função de hash predefinida. (Herdado de Object) |
| GetLifetimeService() |
Recupera o objeto de serviço de tempo de vida atual que controla a política de vida útil neste caso. (Herdado de MarshalByRefObject) |
| GetType() |
Obtém o Type da instância atual. (Herdado de Object) |
| InitializeLifetimeService() |
Obtém-se um objeto de serviço vitalício para controlar a apólice vitalícia neste caso. (Herdado de MarshalByRefObject) |
| MemberwiseClone() |
Cria uma cópia superficial do atual Object. (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 já existir, com o acesso de segurança desejado. |
| OpenExisting(String) |
Abre o mutex nomeado especificado, se já existir. |
| ReleaseMutex() |
Liberta uma Mutex vez. |
| SetAccessControl(MutexSecurity) |
Define a segurança de controlo de acesso para um mutex do sistema nomeado. |
| ToString() |
Devolve uma cadeia que representa o objeto atual. (Herdado de Object) |
| TryOpenExisting(String, Mutex) |
Abre o mutex nomeado especificado, se já existir, e devolve 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 devolve um valor que indica se a operação foi bem-sucedida. |
| WaitOne() |
Bloqueia a linha de corrente até que a corrente WaitHandle receba um sinal. (Herdado de WaitHandle) |
| WaitOne(Int32, Boolean) |
Bloqueia o thread atual até que a corrente WaitHandle receba um sinal, usando um inteiro assinado de 32 bits para especificar o intervalo de tempo e especificando se deve sair do domínio de sincronização antes da espera. (Herdado de WaitHandle) |
| WaitOne(Int32) |
Bloqueia a thread da corrente até que a corrente WaitHandle receba um sinal, usando um inteiro assinado 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 a TimeSpan para especificar o intervalo de tempo e especificando se deve sair do domínio de sincronização antes da espera. (Herdado de WaitHandle) |
| WaitOne(TimeSpan) |
Bloqueia o thread atual até que a instância atual receba um sinal, usando a TimeSpan para especificar o intervalo de tempo. (Herdado de WaitHandle) |
Implementações de Interface Explícita
| Name | Description |
|---|---|
| IDisposable.Dispose() |
Esta API suporta a infraestrutura de produtos e não é pressuposta para ser utilizada diretamente a partir do seu código. Liberta todos os recursos utilizados pelo WaitHandle. (Herdado de WaitHandle) |
Métodos da Extensão
| Name | Description |
|---|---|
| GetSafeWaitHandle(WaitHandle) |
Obtém o handle seguro para um handle de espera nativo do sistema operativo. |
| SetSafeWaitHandle(WaitHandle, SafeWaitHandle) |
Define um handle seguro para um handle de espera nativo do sistema operativo. |
Aplica-se a
Segurança de Thread
Este tipo é seguro para fios.
Ver também
- WaitHandle
- Thread
- de threading gerenciado
- Mutexes