В чем разница между блокировкой и мьютексом?

Ответы:

146

Замок является специфическим для AppDomain, в то время как Мьютекс к операционной системе позволяет выполнять между процессами блокировки и синхронизации (IPC).

Дарин Димитров
источник
96

lockявляется ключевым словом компилятора, а не фактическим классом или объектом. Это оболочка для функциональности Monitorкласса, призванная Monitorупростить работу в общем случае.

Как сказал Дарин, Monitorlockключевое слово) ограничены расширением AppDomain. В первую очередь потому, что ссылка на адрес памяти (в форме созданного объекта) требуется для управления «блокировкой» и поддержания идентичностиMonitor

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

Тоби
источник
54

A Mutexможет быть либо локальным для процесса, либо общесистемным . MSDN :

Мьютексы бывают двух типов: локальные мьютексы, которые не имеют имени, и именованные системные мьютексы. Локальный мьютекс существует только в вашем процессе.

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

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

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

Другое отличие заключается в том, что указывают другие: имя Mutex может использоваться во всех процессах.

Если у кого-то нет особых потребностей или требуется синхронизация между процессами, лучше придерживаться lock(иначе 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 -> Простой в использовании, оболочка на мониторе, блокирует потоки в домене приложений.

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

Именованный мьютекс -> область блокировки - это даже больше, чем безымянный мьютекс, и он распространяется на процесс в операционной системе.

Итак, теперь есть варианты, вам нужно выбрать тот, который лучше всего подходит для вашего случая.

Пракаш Трипати
источник
Как я понял из ответов и примеров для мьютекса здесь msdn.microsoft.com/en-us/library/… : безымянный мьютекс действует так же, как блокировка. Однако mutex.WaitOne (1000) дает нам шанс тайм-аут блокировки. С другой стороны, Monitor.TryEnter также дает нам такую ​​возможность. Как уже упоминалось, Mutex - это оболочка. Поэтому я бы использовал блокировку или монитор вместо безымянного мьютекса. Но если требуется блокировка процессов, можно использовать именованный мьютекс. Пожалуйста, поправьте меня, если я ошибаюсь.
Корай
6

Mutex - это перекрестный процесс, и будет классический пример, когда не запускается более одного экземпляра приложения.

Второй пример: у вас есть файл, и вы не хотите, чтобы другой процесс обращался к одному и тому же файлу, вы можете реализовать Mutex, но помните одну вещь Mutex - это операционная система в целом и не может использоваться между двумя удаленными процессами.

Блокировка - это самый простой способ защитить часть вашего кода, и она зависит от домена приложения, вы можете заменить блокировку на Moniters, если хотите более контролируемую синхронизацию.

TalentTuner
источник
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, который помечен как общедоступный и используется откуда угодно.

Просто тень
источник