Answers:
A Mutex
可以是本地进程,也可以是系统范围的。MSDN:
互斥锁有两种类型:未命名的本地互斥锁和已命名的系统互斥锁。本地互斥仅存在于您的进程中。
此外,在具有终端服务的系统上使用系统范围的互斥锁时,应格外小心-在同一页面上也有详细介绍。
Mutex
和之间的区别之一lock
是Mutex
利用内核级构造,因此同步将始终至少需要用户空间-内核空间转换。
lock
-这实际上是Monitor
该类的捷径,另一方面,它试图避免分配内核资源并过渡到内核代码(因此更加精简和快速-如果必须找到与其相似的WinAPI构造,那就是CriticalSection
)。
另一个区别是其他人指出的是:可以在进程之间使用命名 。Mutex
除非有特殊需要或需要跨流程同步,否则最好坚持lock
(aka Monitor
)˛
还有其他一些“次要”差异,例如如何处理遗弃等。
可以在3.5 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- >简单易用,在监视器上包装,可在AppDomain中跨线程锁定。
未命名的互斥锁 ->与锁类似,除了锁作用域更大,并且在整个过程中贯穿AppDomain。
命名互斥锁 ->锁定范围甚至比未命名的互斥锁还多,并且它在操作系统中跨进程。
因此,现在有了选项,您需要选择最适合自己的情况。
答案中未提及的其他一些细微差异:
在使用锁的情况下,可以确保当锁的块内发生异常时释放该锁。
这是因为该锁在内部使用了监视器,并且是通过以下方式实现的:
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。