Qual é a diferença entre lock e Mutex?

129

Qual é a diferença entre lock e Mutex? Por que eles não podem ser usados ​​de forma intercambiável?

RAM
fonte

Respostas:

146

Um bloqueio é específico para o AppDomain, enquanto o Mutex para o sistema operacional permite executar o bloqueio e sincronização entre processos (IPC).

Darin Dimitrov
fonte
95

locké uma palavra-chave do compilador, não uma classe ou objeto real. É um invólucro da funcionalidade da Monitorclasse e foi projetado para facilitar o Monitortrabalho no caso comum.

O Monitor(e a lockpalavra - chave) são, como Darin disse, restritos ao AppDomain. Principalmente porque é necessária uma referência a um endereço de memória (na forma de um objeto instanciado) para gerenciar o "bloqueio" e manter a identidade doMonitor

O Mutex, por outro lado, é um invólucro .Net em torno de uma construção de sistema operacional e pode ser usado para sincronização em todo o sistema, usando dados de string (em vez de um ponteiro para dados) como seu identificador. Dois mutexes que referenciam duas seqüências de caracteres em dois endereços de memória completamente diferentes, mas com os mesmos dados , realmente utilizarão o mesmo mutex do sistema operacional.

Toby
fonte
54

A Mutexpode ser local para um processo ou para todo o sistema . MSDN :

Mutexes são de dois tipos: mutexes locais, sem nome, e nomeados mutexes do sistema. Um mutex local existe apenas dentro do seu processo.

Além disso, deve-se ter um cuidado especial - detalhado também na mesma página - ao usar um mutex em todo o sistema em um sistema com os Serviços de Terminal.

Uma das diferenças entre Mutexe locké que Mutexutiliza uma construção no nível do kernel , portanto, a sincronização sempre exigirá pelo menos uma transição de espaço do usuário para o espaço do kernel.

lock- isso é realmente um atalho para a Monitorclasse , por outro lado, tenta evitar a alocação de recursos do kernel e a transição para o código do kernel (e, portanto, é mais enxuto e rápido - se for necessário encontrar uma construção WinAPI com a qual ela se assemelha CriticalSection).

A outra diferença é o que os outros apontam: uma lata nomeada Mutex ser usado entre processos.

A menos que alguém tenha necessidades especiais ou exija sincronização entre processos, é melhor se ater a lock(aka Monitor) ˛

Existem várias outras diferenças "menores", como a maneira como o abandono é tratado, etc.

O mesmo pode ser dito sobre ReaderWriterLocke ReaderWriterLockSlimno 3.5, Semaphoree o novo SemaphoreSlimno .NET 4.0 etc. É verdade que as últimas xxSlimclasses não podem ser usadas como primitivas de sincronização em todo o sistema, mas nunca foram feitas para isso - elas foram "apenas" para ser mais rápido e mais amigável aos recursos.

Andras Vass
fonte
25

Eu uso um Mutex para verificar se eu já tenho uma cópia do aplicativo em execução na mesma máquina.

bool firstInstance;
Mutex mutex = new Mutex(false, @"Local\DASHBOARD_MAIN_APPLICATION", out firstInstance);

if (!firstInstance)
{
    //another copy of this application running 
}
else
{
    //run main application loop here.
}
// Refer to the mutex down here so garbage collection doesn't chuck it out.
GC.KeepAlive(mutex);
Jonathan
fonte
8

Muito já foi dito, mas para simplificar, aqui está minha opinião.

lock -> Simples de usar, wrapper no monitor, bloqueia os threads em um AppDomain.

mutex sem nome -> semelhante ao bloqueio, exceto que o escopo de bloqueio é maior e está no AppDomain em um processo.

O mutex nomeado -> o escopo de bloqueio é ainda mais do que o mutex não nomeado e está em processo no sistema operacional.

Portanto, agora existem opções, você precisa escolher a que melhor se adapta ao seu caso.

Prakash Tripathi
fonte
Como entendi a partir das respostas e dos exemplos de mutex aqui, msdn.microsoft.com/en-us/library/… : um mutex sem nome atua da mesma forma que um bloqueio. No entanto, mutex.WaitOne (1000) nos dá a chance de atingir o tempo limite do bloqueio. Por outro lado, o Monitor.TryEnter também nos oferece essa capacidade. Como mencionado, o Mutex é um invólucro. Então, eu usaria um bloqueio ou monitor em vez de um mutex sem nome. Mas se for necessário bloquear os processos, um mutex nomeado é o caminho a percorrer. Por favor corrija-me se eu estiver errado.
Koray
6

O Mutex é um processo cruzado e haverá um exemplo clássico de não executar mais de uma instância de um aplicativo.

O segundo exemplo é que você está tendo um arquivo e não deseja que processos diferentes acessem o mesmo arquivo, você pode implementar um Mutex, mas lembre-se de uma coisa: o Mutex é um sistema operacional amplo e não pode ser usado entre dois processos remotos.

O bloqueio é uma maneira mais simples de proteger a seção do seu código e é específico do domínio do aplicativo. Você pode substituir o bloqueio pelo Moniters se desejar uma sincronização mais controlada.

TalentTuner
fonte
1

Mais algumas pequenas diferenças que não foram mencionadas nas respostas:

  1. No caso de usar bloqueios, você pode ter certeza de que o bloqueio será liberado quando ocorrer uma exceção dentro do bloco do bloqueio.
    Isso ocorre porque o bloqueio usa monitores sob o capô e é implementado desta maneira:

     object __lockObj = x;
     bool __lockWasTaken = false;
     try
     {
         System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
         // Your code...
     }
     finally
     {
         if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
     }

    Portanto, em qualquer caso, o bloqueio é liberado e você não precisa liberá-lo manualmente (como faria nos mutexes).

  2. Para bloqueios, você geralmente usa um objeto privado para bloquear (e deve usar ).
    Isso é feito por vários motivos. (Mais informações: consulte esta resposta e documentação oficial ).

Portanto, no caso de bloqueios, você não pode (acidentalmente obter) acesso ao objeto bloqueado do lado de fora e causar alguns danos.
Mas no caso do Mutex, você pode, como é comum ter um Mutex que é marcado como público e usado de qualquer lugar.

Just Shadow
fonte