【发布时间】:2017-09-23 04:08:03
【问题描述】:
在实时多线程应用程序中检测死锁的方法有哪些?
如果我们发现有死锁,有什么方法可以在不关闭/重新启动应用程序的情况下解决它?
【问题讨论】:
标签: multithreading thread-safety deadlock
在实时多线程应用程序中检测死锁的方法有哪些?
如果我们发现有死锁,有什么方法可以在不关闭/重新启动应用程序的情况下解决它?
【问题讨论】:
标签: multithreading thread-safety deadlock
有两种流行的检测死锁的方法。
一种是让线程设置检查点。例如,如果您有一个具有工作循环的线程,则在开始工作时设置一个计时器,该计时器设置的时间比您认为工作可能花费的时间要长。如果计时器触发,则假定线程已死锁。工作完成后,您取消计时器。
另一个(有时组合使用)是让线程可能阻塞的东西跟踪线程可能持有的其他资源。当其他线程以相反的顺序获取这些锁时,这可以直接检测到尝试获取一个锁同时持有另一个锁的尝试。
这甚至可以在没有实际发生死锁的情况下检测死锁风险。如果一个线程先获得锁A然后B,另一个线程获得锁B然后A,除非它们重叠,否则不会出现死锁。但是这个方法可以检测到。
高级死锁检测通常仅在调试期间使用。除了对应用程序进行编码以检查每个阻塞锁是否存在可能的死锁并知道如果发生死锁该怎么办,死锁后您唯一能做的就是关闭应用程序。不能盲目释放锁,因为它们保护的资源可能处于不一致的状态。
有时您故意编写您知道会死锁的代码并专门对其进行编码以避免该问题。例如,如果您知道许多线程获取锁 A 然后尝试获取锁 B,而其他一些线程需要执行相反的操作,您可以编写代码以执行非阻塞尝试锁定 B 并在失败时释放锁 A .
通常,花精力使死锁变得不可能比让代码检测和解决死锁更有用。
【讨论】:
Python 有一个称为faulthandler 的功能,它对于处理死锁非常有用:
import faulthandler
faulthandler.register(signal.SIGUSR1)
如果您使用 C++ 或任何使用 glibc 的编译器,您可以使用 execinfo.h 中的 backtrace() 函数打印堆栈跟踪,并在收到信号时优雅退出。您可以获取一个死锁的程序,向它发送一个信号并获取所有线程的列表。
在 Java 中,对卡住的进程使用 jstack <pid>。
【讨论】: