Ответы:
lock
является ключевым словом компилятора, а не фактическим классом или объектом. Это оболочка для функциональности Monitor
класса, призванная Monitor
упростить работу в общем случае.
Как сказал Дарин, Monitor
(и lock
ключевое слово) ограничены расширением AppDomain
. В первую очередь потому, что ссылка на адрес памяти (в форме созданного объекта) требуется для управления «блокировкой» и поддержания идентичностиMonitor
С Mutex
другой стороны, это оболочка .Net вокруг конструкции операционной системы, которая может использоваться для общесистемной синхронизации с использованием строковых данных (вместо указателя на данные) в качестве идентификатора. Два мьютекса, которые ссылаются на две строки в двух совершенно разных адресах памяти, но имеют одинаковые данные , фактически будут использовать один и тот же мьютекс операционной системы.
A Mutex
может быть либо локальным для процесса, либо общесистемным . MSDN :
Мьютексы бывают двух типов: локальные мьютексы, которые не имеют имени, и именованные системные мьютексы. Локальный мьютекс существует только в вашем процессе.
Более того, следует проявлять особую осторожность - подробно описанную на той же странице - при использовании общесистемного мьютекса в системе со службами терминалов.
Одно из различий между Mutex
и lock
заключается в том, что в нем Mutex
используется конструкция уровня ядра , поэтому для синхронизации всегда потребуется как минимум переход между пространством пользователя и пространством ядра.
lock
- это действительно ярлык для Monitor
класса , с другой стороны, он пытается избежать выделения ресурсов ядра и перехода к коду ядра (и, таким образом, он более компактный и быстрый - если нужно найти конструкцию WinAPI, которая похожа, это будет CriticalSection
).
Другое отличие заключается в том, что указывают другие: имя Mutex
может использоваться во всех процессах.
Если у кого-то нет особых потребностей или требуется синхронизация между процессами, лучше придерживаться lock
(иначе Monitor
) ˛
Есть несколько других «незначительных» отличий, например, как обрабатывается отказ и т. Д.
То же самое можно сказать и о ReaderWriterLock
и ReaderWriterLockSlim
в 3,5, Semaphore
а новый SemaphoreSlim
в .NET 4.0 и т.д. Это правда , что последние xxSlim
классы не могут быть использованы в качестве общесистемных примитивов синхронизации, но они никогда не были предназначены , чтобы - они были «только» означает , чтобы быть быстрее и удобнее в использовании.
Я использую 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);
Уже много было сказано, но, чтобы упростить, вот мой вывод.
lock -> Простой в использовании, оболочка на мониторе, блокирует потоки в домене приложений.
безымянный мьютекс -> похож на блокировку, за исключением того, что область блокировки больше, и она распространяется на домен приложения в процессе.
Именованный мьютекс -> область блокировки - это даже больше, чем безымянный мьютекс, и он распространяется на процесс в операционной системе.
Итак, теперь есть варианты, вам нужно выбрать тот, который лучше всего подходит для вашего случая.
Mutex - это перекрестный процесс, и будет классический пример, когда не запускается более одного экземпляра приложения.
Второй пример: у вас есть файл, и вы не хотите, чтобы другой процесс обращался к одному и тому же файлу, вы можете реализовать Mutex, но помните одну вещь Mutex - это операционная система в целом и не может использоваться между двумя удаленными процессами.
Блокировка - это самый простой способ защитить часть вашего кода, и она зависит от домена приложения, вы можете заменить блокировку на Moniters, если хотите более контролируемую синхронизацию.
Еще несколько незначительных отличий, не упомянутых в ответах:
В случае использования блокировок вы можете быть уверены, что блокировка будет снята, когда в блоке блокировки произойдет исключение.
Это потому, что замок использует мониторы под капотом и реализован следующим образом:
object __lockObj = x;
bool __lockWasTaken = false;
try
{
System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
// Your code...
}
finally
{
if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
}
Таким образом, в любом случае блокировка снимается, и вам не нужно снимать ее вручную (как если бы вы это делали для мьютексов).
Для блокировок вы обычно используете закрытый объект для блокировки (и должны использовать ).
Это делается по многим причинам. (Дополнительная информация: см. Этот ответ и официальную документацию ).
Таким образом, в случае замков вы не можете (случайно получить) доступ к заблокированному объекту извне и нанести некоторый ущерб.
Но в случае с Mutex вы можете, так как обычно есть Mutex, который помечен как общедоступный и используется откуда угодно.