lock和Mutex有什么区别?

时间:2010-09-17 12:29:24

标签: c# multithreading synchronization

lock和Mutex有什么区别?为什么它们不能互换使用?

7 个答案:

答案 0 :(得分:127)

A lock特定于AppDomain,而Mutex特定于操作系统,允许您执行进程间锁定和同步(IPC)。

答案 1 :(得分:83)

lock是编译器关键字,而不是实际的类或对象。它是Monitor类功能的包装,旨在使Monitor更易于处理常见情况。

正如Darin所说,Monitor(以及lock关键字)仅限于AppDomain。主要是因为需要引用内存地址(以实例化对象的形式)来管理“锁定”并保持Monitor的身份

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

答案 2 :(得分:48)

Mutex可以本地到流程或系统范围MSDN

  

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

此外,在使用终端服务的系统上使用系统范围的互斥锁时,应特别小心 - 在同一页面上详细说明。

Mutexlock之间的区别之一是Mutex使用kernel-level construct,因此同步始终至少需要用户空间 - 内核空间转换。< / p>

lock - 这实际上是Monitor class的快捷方式,另一方面试图避免分配内核资源并转换到内核代码(因此更精简和更快 - 如果必须的话找到一个类似的WinAPI构造,它将是CriticalSection)。

另一个区别在于其他人指出:名为 Mutex 可以跨进程使用。

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

还有其他一些“轻微”的差异,比如放弃处理等等。

关于3.5 ReaderWriterLock中的ReaderWriterLockSlimSemaphore以及.NET 4.0等中的新SemaphoreSlim,也可以这样说。 确实,后面的xxSlim类不能用作系统范围的同步原语,但它们从未意图 - 它们“仅”意味着更快,更加资源友好。

答案 3 :(得分:21)

我使用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);

答案 4 :(得分:6)

Mutex是一个跨流程,会有一个不运行多个应用程序实例的经典示例。

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

锁定是保护代码部分的最简单方法,它是特定于应用程序域的,如果您想要更加可控的同步,可以用Moniters替换锁定。

答案 5 :(得分:5)

已经说了很多,但为了简单起见,这就是我的看法。

锁定 - &gt;易于使用,监视器上的包装器,锁定AppDomain中的线程。

未命名的互斥锁 - &gt;类似于锁,除了锁定范围更多,它在进程中的AppDomain之间。

命名互斥 - &gt;锁定范围甚至超过了未命名的互斥锁,它与操作系统中的进程不同。

所以现在有选择,您需要选择最适合您的选项。

答案 6 :(得分:1)

答案中未提及的其他一些细微差别:

  1. 对于使用锁的情况,可以确保当锁的块中发生异常时,将释放该锁。
    这是因为该锁在内部使用了监视器,并且是通过this方式实现的:

     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. 对于锁,通常使用私有对象进行锁定(并且应使用)。
    这样做有很多原因。 (更多信息:see this answerofficial documentation)。

因此,在发生锁定的情况下,您不能(偶然获得)从外部访问锁定的对象并造成一些损坏。
但是对于Mutex,您可以这样做,因为通常有一个标记为公开并可以在任何地方使用的Mutex。