lock和Mutex有什么区别?


Answers:



95

lock是一个编译器关键字,而不是实际的类或对象。它是Monitor该类功能的包装,旨在使Monitor在普通情况下更易于使用。

Monitor(和lock关键字)是,如达林所述,受限于AppDomain。主要是因为需要引用内存地址(以实例化对象的形式)来管理“锁”并维护内存的标识。Monitor

Mutex,在另一方面,是一个NET包装围绕一操作系统构建体中,并且可以使用串被用于系统范围内同步,数据(而不是数据指针)作为其识别符。引用两个完全不同的内存地址中的两个字符串但具有相同数据的两个互斥锁实际上将使用相同的操作系统互斥锁。


54

A Mutex可以是本地进程,也可以系统范围的MSDN

互斥锁有两种类型:未命名的本地互斥锁和已命名的系统互斥锁。本地互斥仅存在于您的进程中。

此外,在具有终端服务的系统上使用系统范围的互斥锁时,应格外小心-在同一页面上也有详细介绍。

Mutex和之间的区别之一lockMutex利用内核级构造,因此同步将始终至少需要用户空间-内核空间转换。

lock-这实际上是Monitor该类的捷径,另一方面,它试图避免分配内核资源并过渡到内核代码(因此更加精简和快速-如果必须找到与其相似的WinAPI构造,那就是CriticalSection)。

另一个区别是其他人指出的是:可以在进程之间使用命名Mutex

除非有特殊需要或需要跨流程同步,否则最好坚持lock(aka Monitor)˛

还有其他一些“次要”差异,例如如何处理遗弃等。

可以在3.5 ReaderWriterLockReaderWriterLockSlim3.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中跨线程锁定。

未命名的互斥锁 ->与锁类似,除了锁作用域更大,并且在整个过程中贯穿AppDomain。

命名互斥锁 ->锁定范围甚至比未命名的互斥锁还多,并且它在操作系统中跨进程。

因此,现在有了选项,您需要选择最适合自己的情况。


从我从此处的答案和互斥锁示例中了解到,msdn.microsoft.com / zh-cn / library /…:未命名的互斥锁与锁的作用相同。但是,mutex.WaitOne(1000)使我们有机会超时锁定。另一方面,Monitor.TryEnter也提供了这一功能。如前所述,Mutex是包装器。因此,我将使用锁或Monitor而不是未命名的互斥锁。但是,如果需要跨进程锁定,则必须使用命名互斥锁。如果我错了,请纠正我。
Koray

6

Mutex是一个跨进程,并且将有一个经典示例,其中该示例不运行一个应用程序的多个实例。

第二个例子是说您有一个文件,并且您不希望其他进程访问同一文件,您可以实现Mutex,但请记住,Mutex是操作系统范围的,不能在两个远程进程之间使用。

锁定是保护代码部分的最简单方法,并且它是appdomain特定的,如果您想要更多受控的同步,则可以用Moniters替换锁定。


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。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.