线程因互斥锁而崩溃

Posted

技术标签:

【中文标题】线程因互斥锁而崩溃【英文标题】:Thread crashed with locked Mutex 【发布时间】:2010-07-02 07:15:22 【问题描述】:

有一个场景,我有两个线程都使用相同的互斥锁。一个线程锁定了互斥锁并崩溃了。互斥锁状态是什么?它是否仍然被锁定并且第二个线程从未拥有该互斥锁?意味着死锁情况?

编辑——同时解释一个Linux系统上的pthread案例

【问题讨论】:

请提供更多信息。 【参考方案1】:

由于你没有指定什么操作系统,我来告诉你在 Win32 中会发生什么。

在 Win32 中,第二个线程在等待已终止线程拥有的互斥锁时将获得 WAIT_ABANDONED。 注意,接收到WAIT_ABANDONED意味着第二个线程已经接收到互斥体,所以不会出现死锁。第二个线程应该检测到WAIT_ABANDONED结果,并验证受互斥体保护的资源是否有效状态。如果它可以检测到损坏并且没有检测到任何损坏,则可以安全地继续。如果没有,最好提出某种错误。

对于互斥锁的某些实现,无法检测到拥有它的线程是否已终止,最终导致死锁。

对于互斥体的某些实现,有一种方法可以检测拥有线程是什么,确定拥有线程已终止,然后取得互斥体的所有权。

【讨论】:

在某些实现中,您可以定义等待时间或创建自己的包装方法...无论如何,线程挂起对经典实现中的互斥体\信号量没有影响,因此检查等待时间和引发超时异常或恢复执行。 抱歉半个问题。这是在 Windows 操作系统上,也想知道其他操作系统的行为。 Gabe:如果它总是得到 WAIT_ABANDONED,那么很容易处理。再次,有死锁吗?我们如何检测所有者线程已崩溃。 Joonas Pulakka:假设线程因 NULL 而崩溃。表示没有例外或没有任何承认。【参考方案2】:

这当然取决于(至少)两件事:

互斥锁是如何实现的,以及 线程如何崩溃(是抛出异常,还是只是“消失”)。

例如,在 Java 的 synchronized 中,保证在“线程处理完对象”时释放块——无论这意味着什么(参见 link)。根据this文章:

停止线程会导致它解锁所有已锁定的监视器。

好的,stop()ing 线程释放了监视器,但是如果一个线程以某种方式消失了,那么它是否“完成了对象”?我在任何地方都没有看到这个记录。但很明显,某人必须释放锁定的互斥体,否则它们会死锁;也许某些互斥锁或环境包含在锁定互斥锁的线程不存在时自动释放互斥锁的机制。

另一个例子:java.util.concurrent.Lock 文档建议使用finally 语句来释放锁,这样无论执行线程发生什么,锁都会被释放。但是,如果线程在finally 语句被执行之前消失了,那么锁永远不会被释放并且确实会发生死锁。当然,线程不应该就这样“消失”。

很好的问题!

【讨论】:

问题很好,但每个实现都有自己的机制和解决方案来解决所描述的问题,但我们只能猜测作者的意思:)【参考方案3】:

感谢您的回复。 http://msdn.microsoft.com/en-us/library/ms687032%28VS.85%29.aspx MSDN 还说它释放了互斥锁,等待线程获得 WAIT_ABANDONED 状态。

【讨论】:

以上是关于线程因互斥锁而崩溃的主要内容,如果未能解决你的问题,请参考以下文章

高并发编程-09-读写锁ReentrantReadWriteLock

多线程安全----同步锁(互斥锁)

为啥互斥锁不需要互斥锁(而互斥锁需要互斥锁......)

多线程之线程同步(互斥锁信号量条件变量和读写锁​)

多线程之线程同步(互斥锁信号量条件变量和读写锁​)

多线程之线程同步(互斥锁信号量条件变量和读写锁​)