我应该处置互斥锁吗?
Posted
技术标签:
【中文标题】我应该处置互斥锁吗?【英文标题】:Should I dispose a Mutex? 【发布时间】:2011-08-18 12:01:07 【问题描述】:我正在开发 2 个 Windows 服务,它们有一个公共数据库,我想用系统互斥锁锁定(跨进程)。
现在我想知道在try-finally
块中调用WaitOne()
和ReleaseMutex()
是否可以,或者我是否也应该处理互斥锁(例如在using
块中)。如果是这样,我想我应该总是在 WaitOne()
方法上捕获 AbandonedMutexException
还是我错了?
【问题讨论】:
您需要 AbandonedMutexException 来告诉您拥有互斥锁的服务已意外终止。在这种情况下,您必须停止使用 dbase 并等待其他服务再次启动。使用第三个进程作为仲裁者是明智的。 【参考方案1】:互斥锁是一个 Windows 内核对象(这里包装在一个 .NET 对象中)。
因此,它是一个应该被释放的非托管资源。
更准确地说,.NET 对象包含互斥体的句柄,必须以某种方式释放/处置。
我不相信没有释放互斥对象的code sample in the Mutex class docs。尽管 Henzi 有一个很好的评论点:Mutex 对象是静态的,并且会在进程退出时由终结器处置或由 Windows 内核销毁。
另外,请注意Close() 也会处理该对象。
当然,将现有的 Mutex 对象保留在您的应用程序中并没有错,即使您不使用它也是如此。它们是轻资源。
【讨论】:
没有留下代码示例,你必须链接它:msdn.microsoft.com/en-us/library/system.threading.mutex.aspx 但是由于我正在创建 Windows 服务,我认为我不应该在我的服务的“运行时”期间进行处理(总是如此)。每次创建一个具有相同名称的新 Mutex 实例只会包装相同的非托管实例,对吗?还是会一遍又一遍地创建新的非托管资源?当我的一项服务停止以真正清理它时,我可以关闭互斥锁吗? 在代码示例中,创建了一个互斥体,它存储在一个静态字段中,并在应用程序的整个持续时间内使用。当应用程序终止时,会自动调用终结器。那么,处置该互斥体有什么意义呢? (不过,我确实同意你的观点,一般所有 IDisposable 对象都应该被释放。我只是不同意代码示例中缺少某些东西的事实。) Serge,我认为问题在于这个互斥锁将由两个 Windows 服务共享。因此,必须停止两者才能运行终结器。如果某些东西实现了 IDisposable,请始终确保调用 Dispose。 否 - 每个进程都有自己的 HANDLE...所以终结器只会删除那个 HANDLE...当没有更多 HANDLE 时,内核对象本身最终会被 Windows 销毁(在此示例中= 没有更多的进程)到那个 Mutex...【参考方案2】:根据this,当最后一个持有该互斥体的HANDLE
的进程结束时,名为Mutex
的名称会自动销毁。
在非托管术语中,MSDN 说
使用
CloseHandle
函数关闭句柄。当进程终止时,系统会自动关闭句柄。互斥对象在其最后一个句柄关闭时被销毁。
在 .NET 中,您应该在 Mutex
上调用 .Close()
- 这会释放 HANDLE
... 因为每个进程在访问相同名称的 HANDLE
时都会获得自己的 HANDLE
,这是一致的做法。 .. 不调用 Close()
不会留下任何问题,一旦进程不再(终结器和所有)......
【讨论】:
【参考方案3】:您需要释放等待句柄使用的资源。
来自文档:
释放当前 WaitHandle 实例使用的所有资源 班级。 (继承自 WaitHandle。)
等待句柄使用非托管资源,应在使用结束时释放。
MSDN Documentation Mutex
【讨论】:
以上是关于我应该处置互斥锁吗?的主要内容,如果未能解决你的问题,请参考以下文章
使用互斥锁后程序仍然崩溃(我可以在同一个线程中使用互斥锁吗?)
我可以使用联锁操作来更新多个值以避免锁定关键部分/互斥锁吗?