Skip to content

Mutex 的正确打开方式

Published: at 22:00

在使用 Mutex 在给线程/进程间加锁时,需要注意的问题。

1 AbandonedMutexException

在使用 mutex.WaitOne 时,可能抛出异常 AbandonedMutexException 。

有一个线程获得了锁,但没有释放锁,则会抛异常,此时数据的完整性可能被破坏。
具体解释见:AbandonedMutexException Class (System.Threading) | Microsoft Docs

比如:在 WaitOne 之后,进程直接退出,后台线程中的 mutex 可能就还没有释放。

如果不关心这个异常,可以直接 catch ,继续进行接来下的操作即可。无需再次调用 WaitOne

try
{
try
{
mutex.WaitOne();
}
catch(AbandonedMutexException)
{
// 即使捕获到这个异常,此时也已经获得了锁
}
// do something
}
finally
{
mutex.ReleaseMutex();
}

考虑如下场景,运行 run.exe 程序,里面获取了 mutex 锁,没有释放直接退出,再次打开 run.exe ,是不会有 AbandonedMutexException 异常的。 但如果同时运行两个(多个) run.exe 程序,第一个获取锁之后不释放直接退出,则第二个 run.exe 会捕捉到 AbandonedMutexException 异常。

原因(猜测):
在只有一个 run.exe 进程时,关闭之后,mutex 对应的内核对象随之释放,第二次运行,新建一个全新的 mutex 内核对象;
而当有两个(多个)run.exe 进程时,mutex 对象始终只有一个。

2 System.ApplicationException

当 WaitOne 对应的 ReleaseMutex 不在同一线程时,会抛出异常:System.ApplicationException:“从不同步的代码块中调用了对象同步方法。”

3 关于 WaitOne 与 ReleaseMutex 的次数


更多内容,可以参阅: .NET 中使用 Mutex 进行跨越进程边界的同步 - walterlv


原文链接: https://blog.jgrass.cc/posts/csharp-mutex/

本作品采用 「署名 4.0 国际」 许可协议进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。