通缉:不受AbandonedMutexException影响的跨进程同步

我有几个线程获取互斥体,然后终止。

互斥体存储在主存储库中,并在程序存在时正确释放。 但是,当分配一个互斥体的线程存在时,互斥体会自动释放,并随后获取AbandonedMutexException(也根据文档 )。

我怎样才能避免这种exception,即使分配线程完成后仍继续使用互斥锁? .Net中是否有另一个更合适的同步构造,没有这个限制。

– 我正在寻找一个跨进程同步机制,它具有与Mutex类似的语义。

回答这个问题

AFAIK不存在这样的互斥体类。 AbandonedMutexException是相当烦人的,但它代表了一个真实的情况,可能会出现没有自动解决方案。

当你有跨进程,甚至跨线程交流时,你必须处理这样的事实,任何一个参与实体可能是意想不到的,并突然终止由于许多原因。 互斥体的存在是为了保护资源,如果一个线程在拥有一个互斥锁的时候被放弃,那么操作系统就无法保证它以任何一致的方式保留数据。 这是非常重要的,因为这意味着放弃线程可能已经使某些不变量被其他线程所依赖。

AbandonedMutexException是主动说“坏事发生了,现在处于不确定状态”的一种方式。 这里真的没有其他的操作系统补救。

回答你的答案

EventWaitHandle与Mutex不同,用于不同的目的。

互斥锁用于保护特定资源,就像锁定语句一样。 当一个特定的线程获得一个互斥体时,它被认为拥有互斥体。 一次只能有一个主人。 因此,如果涉及到的所有线程都同意只在拥有Mutex的情况下触摸资源,则可以安全地跨线程访问资源

EventWaitHandle可以在一定程度上被视为一个线程安全的事件。 它具有有信号和无信号的概念,任何数量的线程都可以等待它达到信号状态。 当发信号时,其中一个等待线程将被唤醒并开始处理。

您可以使用EventWaitHandle来实现线程安全的一种形式。 锁拥有权不是访问资源的关键,而是从事件中发出信号是访问资源的关键。 然而,魔鬼又一次在细节中。

  1. 谁负责发信号事件? 有了一个互斥体,每一个线程本质上都尖叫着“我是我”,操作系统选择一个线程来获胜。 使用EventWaitHandle,您将负责决定下一个线程何时开始。
  2. 有人通过taskmgr杀死一个进程会发生什么? 如果进程中有一个线程正在响应EventWaitHandle上的事件呢?
  3. 2但是当接下来发出等待手柄的项目被取下时会发生什么? 你必须考虑到这一点,以避免死锁。

看起来像EventWaitHandle做我想要的。 它有一个名字的构造函数,所以它是跨进程同步的最佳选择,它没有这个问题。

收到AbandonedMutexException后,没有什么能够阻止您使用互斥锁。 从文档 :

下一个请求拥有该互斥锁的线程可以处理这个异常并继续执行,只要能够验证数据结构的完整性即可。

当然,这假设你知道你(和你的线程)在崩溃时正在做什么,这基本上意味着获取线程可以在退出之前释放互斥体。

所以最后你使用EvenWaitHandle的解决方案比互斥锁更好。