多线程应用程序中的死锁检测

时间:2014-05-30 03:05:23

标签: c++ multithreading posix solaris semaphore

我使用posix线程使用多线程C ++应用程序,即通过pthread_create创建线程。有几个信号量控制同步。信号量主要有两种:

  1. 互斥信号量 - pthread_mutex_lock和pthread_mutex_unlock调用之间互斥的关键部分代码(由同一个线程完成)

  2. 同步信号量 - 一个线程等待调用sem_wait来完成某些任务,其他线程完成任务后,通过sem_post发出信号。

  3. 在处理大量数据时,应用程序似乎没有响应,但运行时间较长。

    我想到了两种可能性:

    1. 有一个死锁,两个线程正在等待(循环等待)
    2. 父进程(telnet会话)超时,导致向子进程发送SIGHUP信号。
    3. 问题

      1. 我可以通过日志检测死锁吗?例如,在每个等待/发布时,在sem_wait之前,log as as wait,在sem_wait获取锁之后,在sem_post之后等待(无论如何都是非阻塞),记录为signal / post等待进程 - 然后如果程序似乎挂起,检查日志以检测任何循环等待。有没有更好的建议方法?
      2. 使用nohup运行应用程序,以便可以忽略SIGHUP。
      3. 还有其他建议吗?

2 个答案:

答案 0 :(得分:3)

死锁检测可以在更高级别完成,对于进程,死锁检测可以在操作系统级别完成,对于线程,主线程可以检测子线程之间的死锁,如果子线程不需要任何系统 - 等级资源,如I / O等。

检测死锁的一种方法是为共享资源构建资源需求图。假设系统创建了2个线程Ta和Tb,Ta和Tb都需要资源Ra和Rb。如果Ta已经获得Ra并且需要Rb,则这可以类似于有向图:Ra-> Ta-> Rb。如果Tb保持Rb,则这将类似于Ra-> Ta-> Rb-> Tb,没有死锁。但是,如果Tb持有Rb并且需要Ra,则图形将如下:Ra-> Ta-> Rb-> Tb-> Ra,形成环路,这意味着死锁。

对于这种特定的情况,我认为可以检测日志中的死锁,如上所述,比如Ta log:Ra-> Ta-> Rb,以及Tb log,如下所示:Rb-> Tb- > Ra,然后主线程可以检查是否存在循环,但这可能是复杂且昂贵的,因此,更好的方法是仔细使用同步协议,并防止死锁。

答案 1 :(得分:2)

检测死锁是前期设计的问题。 您不应该设计应用程序来检测死锁,您应该努力通过审核和测试将其从设计中消除。

避免/消除设计中的死锁的策略

  • 静态分析工具(Coverity Prevent,clang的{​​{1}}等)
  • 测试
  • RAII

一旦发现死锁,他们通常很容易调查。与堆损坏(跟踪其原点可能很棘手)不同,死锁系统将保持不良状态,直到您开始拯救它。附上调试器并查看堆栈跟踪,问题应该很明显。