Jaka jest różnica między lock i Mutex?

Odpowiedzi:

146

Blokada jest specyficzny dla AppDomain, podczas gdy Mutex do systemu operacyjnego, co pozwala wykonać blokadę między procesami i synchronizacji (IPC).

Darin Dimitrov
źródło
95

lockjest słowem kluczowym kompilatora, a nie rzeczywistą klasą lub obiektem. Jest to opakowanie wokół funkcjonalności Monitorklasy i zostało zaprojektowane tak, aby Monitorułatwić pracę z typowym przypadkiem.

Monitor(I locksłów kluczowych) są, jak powiedział Darin, ograniczone do AppDomain. Przede wszystkim dlatego, że odniesienie do adresu pamięci (w postaci instancji obiektu) jest wymagane do zarządzania „blokadą” i utrzymywania tożsamościMonitor

Z Mutexdrugiej strony, jest otoką .Net wokół konstrukcji systemu operacyjnego i może być używany do synchronizacji w całym systemie, używając danych łańcuchowych (zamiast wskaźnika do danych) jako identyfikatora. Dwa muteksy, które odwołują się do dwóch ciągów w dwóch zupełnie różnych adresach pamięci, ale mają te same dane , będą w rzeczywistości wykorzystywać ten sam muteks systemu operacyjnego.

Toby
źródło
54

MutexMogą być zarówno lokalne do procesu lub w całym systemie . MSDN :

Muteksy są dwojakiego rodzaju: lokalne muteksy, które są nienazwane, oraz nazwane muteksy systemowe. Lokalny mutex istnieje tylko w Twoim procesie.

Ponadto należy zachować szczególną ostrożność - wyszczególniono również na tej samej stronie - podczas korzystania z ogólnosystemowego muteksu w systemie z usługami terminalowymi.

Jedna z różnic między Mutexi lockpolega na tym, że Mutexwykorzystuje konstrukcję na poziomie jądra , więc synchronizacja zawsze będzie wymagać przynajmniej przejścia między przestrzenią użytkownika a przestrzenią jądra.

lock- to jest naprawdę skrót do Monitorklasy , z drugiej strony stara się uniknąć alokacji zasobów jądra i przejścia do kodu jądra (a tym samym jest bardziej oszczędny i szybszy - jeśli trzeba znaleźć konstrukcję WinAPI, która przypomina, to by była CriticalSection).

Inną różnicą jest to, na co wskazują inni: named Mutex może być używany w różnych procesach.

Jeśli ktoś nie ma specjalnych potrzeb lub nie wymaga synchronizacji między procesami, lepiej jest trzymać się lock(aka Monitor) ²

Istnieje kilka innych „drobnych” różnic, na przykład sposób obsługi porzucenia itp.

To samo można powiedzieć o ReaderWriterLocki ReaderWriterLockSlimw 3.5, Semaphorea także o nowościach SemaphoreSlimw .NET 4.0 itd. Prawdą jest, że te ostatnie xxSlimklasy nie mogą być używane jako prymitywy do synchronizacji całego systemu, ale nigdy nie miały do ​​tego celu - miały "tylko" znaczenie być szybszym i bardziej przyjaznym dla zasobów.

Andras Vass
źródło
25

Używam Mutex, aby sprawdzić, czy mam już kopię aplikacji uruchomioną na tym samym komputerze.

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
źródło
8

Wiele już zostało powiedziane, ale aby to uprościć, oto moje podejście.

lock -> Prosty w użyciu, wrapper na monitorze, blokuje wątki w AppDomain.

nienazwany mutex -> podobny do blokady, z tym że zakres blokowania jest czymś więcej i jest w obrębie AppDomain w procesie.

Nazwany mutex -> zakres blokowania to coś więcej niż nienazwany mutex i obejmuje cały proces w systemie operacyjnym.

Więc teraz są dostępne opcje, musisz wybrać ten, który najlepiej pasuje do twojego przypadku.

Prakash Tripathi
źródło
Jak zrozumiałem z odpowiedzi i przykładów muteksu tutaj msdn.microsoft.com/en-us/library/… : nienazwany mutex działa tak samo jak blokada. Jednak mutex.WaitOne (1000) daje nam szansę na przekroczenie limitu czasu blokady. Z drugiej strony, Monitor.TryEnter również daje nam tę możliwość. Jak wspomniano, Mutex to opakowanie. Więc użyłbym blokady lub monitora zamiast nienazwanego muteksu. Ale jeśli wymagana jest blokada między procesami, rozwiązaniem jest nazwany mutex. Proszę, popraw mnie jeśli się mylę.
Koray
6

Mutex jest procesem krzyżowym i będzie klasyczny przykład nie uruchamiania więcej niż jednej instancji aplikacji.

Drugi przykład mówi, że masz plik i nie chcesz, aby inny proces miał dostęp do tego samego pliku, możesz zaimplementować Mutex, ale pamiętaj o jednej rzeczy Mutex jest systemem operacyjnym i nie może być używany między dwoma zdalnymi procesami.

Blokada to najprostszy sposób ochrony sekcji kodu i jest ona zależna od domeny aplikacji. Możesz zastąpić blokadę monitorami, jeśli chcesz bardziej kontrolowaną synchronizację.

TalentTuner
źródło
1

Kilka drobniejszych różnic, które nie zostały wymienione w odpowiedziach:

  1. W przypadku korzystania z zamków możesz być pewien, że blokada zostanie zwolniona, gdy w bloku zamka wydarzy się wyjątek.
    To dlatego, że zamek wykorzystuje monitory pod maską i jest realizowany w ten sposób:

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

    Tak więc w każdym przypadku blokada zostaje zwolniona i nie trzeba jej ręcznie zwalniać (tak jak w przypadku muteksów).

  2. W przypadku Locks zwykle używasz prywatnego obiektu do blokowania (i powinieneś go używać ).
    Dzieje się tak z wielu powodów. (Więcej informacji: zobacz tę odpowiedź i oficjalną dokumentację ).

Tak więc w przypadku zamków nie możesz (przypadkowo uzyskać) dostępu do zamkniętego obiektu z zewnątrz i spowodować pewne uszkodzenia.
Ale w przypadku Mutexa możesz, ponieważ powszechne jest posiadanie Mutexu, który jest oznaczony jako publiczny i używany z dowolnego miejsca.

Just Shadow
źródło