锁和互斥有什么区别?

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

80040 次浏览

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

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

第二个例子是,假设你有一个文件,你不想让不同的进程访问同一个文件,你可以实现一个 Mutex,但要记住一件事,Mutex 是一个操作系统,不能在两个远程进程之间使用。

锁是保护代码段的最简单方法,它是 appdomain 特定的,如果您想要更多的控制同步,可以用 Monitor 替换 Lock。

lock是编译器关键字,而不是实际的类或对象。它是 Monitor类功能的一个包装器,其设计目的是使 Monitor更易于在常见情况下使用。

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

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

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

一个 Mutex可以是一个进程的 要么是本地人,也可以是一个进程的 或整个系统:

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

此外,在具有终端服务的系统上使用系统范围的互斥对象时,应该特别小心——在同一页上也有详细说明。

Mutexlock的区别之一是 Mutex使用 内核级构造,因此同步总是需要至少一个用户空间-内核空间转换。

lock——这确实是通往 Monitor的一条捷径,另一方面,它试图避免分配内核资源和过渡到内核代码(因此更精简和更快捷——如果你必须找到一个类似的 WinAPI 结构,那就是 CriticalSection)。

另一个区别是其他人指出的: 一个 名字 Mutex 可以跨进程使用。

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

还有一些其他的“小”区别,比如如何处理遗弃等等。

3.5中的 ReaderWriterLockReaderWriterLockSlimSemaphore和.NET 4.0中的新 SemaphoreSlim也是如此。 的确,后面的 xxSlim类不能作为系统范围的同步原语使用,但是它们从来没有这个意思——它们“只”意味着更快和更具资源友好性。

已经说了很多了,简单来说,这是我的看法。

Lock -> 简单易用,在监视器上包装,在 AppDomain 中跨线程锁定。

与 lock 类似的未命名互斥锁 -> ,只不过锁定范围更大,并且在进程中跨 AppDomain。

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

所以现在有了选择,你需要选择一个最适合你的情况。

答复中没有提到的几个细微差别:

  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. 对于 Lock,通常使用 私人物品来锁定(和 应该使用)。
    这样做有很多原因。(更多信息: 看看这个答案正式文件)。

因此,在锁定的情况下,您 不行(意外获得)从外部访问被锁定的对象并造成一些损害。
但是对于 Mutex,您可以这样做,因为通常有一个 Mutex,它被标记为 public,可以在任何地方使用。

锁和监视器主要用于为应用程序自身生成的线程(即内部线程)提供线程安全。另一方面,Mutex 确保由外部应用程序(即外部线程)生成的线程的线程安全。使用 Mutex,在任何给定的时间点,只有一个外部线程可以访问我们的应用程序代码。

看看这个