Чим відрізняється замок від Mutex?


Відповіді:



95

lock- це ключове слово компілятора, а не власне клас чи об’єкт. Це обгортка навколо функціональності Monitorкласу і покликана Monitorполегшити роботу з загальною справою.

Як сказала Дарін, Monitorlockключове слово) обмежено значенням AppDomain. Перш за все тому, що для управління "замком" та збереження ідентичності пам'яті потрібне посилання на адресу пам'яті (у вигляді екземпляра)Monitor

З Mutexіншого боку, це .Net обгортка навколо конструкції операційної системи і може використовуватися для загальносистемної синхронізації, використовуючи рядкові дані (замість вказівника на дані) в якості ідентифікатора. Два мутекси, що посилаються на два рядки у двох абсолютно різних адресах пам'яті, але мають однакові дані , фактично використовуватимуть ту саму мутекс операційної системи.


54

А Mutexможе бути локальним для процесу або загальносистемним . MSDN :

Мутекси бувають двох типів: локальні мутекси, які не називаються, та названі системні мутекси. Місцевий мютекс існує лише у вашому процесі.

Крім того, слід бути особливо обережним - детально на тій же самій сторінці - при використанні загальносистемного файлу mutex у системі із службами терміналів.

Однією з відмінностей між Mutexі lockє те, що Mutexвикористовується конструкція на рівні ядра , тому для синхронізації завжди буде потрібно щонайменше перехід простору ядра в простір користувача.

lock- це дійсно ярлик до Monitorкласу , з іншого боку намагається уникати розподілу ресурсів ядра та переходу до коду ядра (і тим самим швидше і швидше - якщо треба знайти конструкцію WinAPI, яка б вона нагадувала, це було б CriticalSection).

Інша відмінність полягає в тому, що вказують інші: названий Mutex може використовуватися в різних процесах.

Якщо хтось не має особливих потреб або не потребує синхронізації між процесами, просто краще дотримуватися lock(aka Monitor) ˛

Існує кілька інших "незначних" відмінностей, як, наприклад, поводження із залишенням тощо.

Те саме можна сказати про ReaderWriterLockі ReaderWriterLockSlimв 3.5, Semaphoreі в новому SemaphoreSlimв .NET 4.0 тощо. Це правда, що останні xxSlimкласи не можна використовувати як примітиви для синхронізації для всієї системи, але вони ніколи не були призначені для цього - вони мали на увазі "лише" щоб бути швидшим та зручнішим для використання ресурсів.


25

Я використовую Mutex, щоб перевірити, чи є у мене вже копія програми, що працює на одній машині.

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);

8

Багато вже було сказано, але щоб зробити це просто, ось мій погляд.

lock -> Простий у використанні, обгортка на моніторі, блокування через потоки в AppDomain.

неназваний mutex -> подібний до блокування, за винятком області блокування більше, і він знаходиться через AppDomain в процесі.

Область фіксації mutex -> навіть більше, ніж неназвана mutex, і вона поширюється в операційній системі.

Тож зараз варіанти є, вам потрібно вибрати той, який найкраще підходить для вашого випадку.


Як я зрозумів з відповідей та прикладів для mutex тут msdn.microsoft.com/en-us/library/… : неназваний мутекс діє так само, як і блокування. Однак mutex.WaitOne (1000) дає нам можливість вимкнути замок. З іншого боку, Monitor.TryEnter також дає нам цю здатність. Як вже згадувалося, Mutex - це обгортка. Тож я б застосував замок або Монітор замість безіменного файлу. Але якщо потрібен блокування в усіх процесах, це ім'я з ім'ям mutex. Будь ласка, виправте мене, якщо я помиляюся.
Корай

6

Mutex - це перехресний процес, і це буде класичний приклад запуску більш ніж одного екземпляра програми.

Другий приклад - це те, що у вас є файл, і ви не хочете, щоб інший процес отримував доступ до одного файлу, ви можете реалізувати Mutex, але пам’ятайте одне, що Mutex - це операційна система, і вона не може використовуватися між двома віддаленими процесами.

Блокування - це найпростіший спосіб захисту розділу вашого коду, і це специфічно для додатка, ви можете замінити блокування на Монітори, якщо ви хочете більш керованої синхронізації.


1

Ще кілька незначних відмінностей, про які не було сказано у відповідях:

  1. У разі використання замків, ви можете бути впевнені, що блокування буде звільнено, коли у блоці блокування стане виняток.
    Це тому, що замок використовує монітори під капотом і реалізується таким чином:

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

    Таким чином, у будь-якому випадку блокування звільняється, і вам не потрібно звільняти його вручну (як це було б зроблено для мютексів).

  2. Для блокування ви зазвичай використовуєте приватний об'єкт для блокування (і його слід використовувати ).
    Це робиться з багатьох причин. (Детальніше: див. Цю відповідь та офіційну документацію ).

Таким чином, у випадку блокування ви не можете (випадково отримати) доступ до заблокованого об’єкта ззовні та завдати певної шкоди.
Але у випадку з Mutex ви можете, так як звичайно мати Mutex, який позначений як загальнодоступний і використовується з будь-якого місця.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.