概念

死锁指的是两个或多个线程彼此等待对方释放所持有的资源,从而导致所有线程都无法继续执行,程序无法继续运行的情况。

  • 死锁是一种静止状态,线程被无限阻塞,直到外部干预,如强制终止某些线程。
  • 死锁发生时,线程无法自行解锁,需要外部的干预来打破循环依赖,释放资源以解决死锁。

产生死锁的原因

  • 系统资源不足。
  • 进程运行推进的顺序不合适。
  • 资源分配不当。

死锁四个必要条件

  • 互斥:进程对已分配的资源独享,其他进程需要等待。
  • 请求保持:进程需要持有已分配的资源,并继续请求其他资源,但他们无法满足请求,导致进程阻塞并保持对已有资源的持有。
  • 不可剥夺:进程已经获得的资源不能被其他进程强制性剥夺。
  • 环路等待:存在多个进程之间形成循环等待资源的关系。

死锁预防

  • 破坏互斥条件:尽可能地共享资源,而不是互斥地独占资源。
  • 破坏请求保持条件:请求资源时先释放已占有的资源,再请求所需的资源,以避免持有资源的阻塞情况。
  • 破坏不可剥夺条件:引入资源抢占机制,使得系统可以对进程已获取的资源进行剥夺。
  • 破坏环路等待条件:通过有序资源分配策略,避免形成循环等待的资源关系。

哲学家就餐问题

银行家算法-预测资源需求

一个数组 state 来记录每一位哲学家在进程、思考还是饥饿状态(正在试图拿叉子)。

那么,一个哲学家只有在两个邻居都没有进餐时,才可以进入进餐状态。

i个哲学家的左邻右舍,则由宏 LEFTRIGHT 定义:LEFT : ( i + 5 - 1 ) % 5 RIGHT : ( i + 1 ) % 5 比如 i2,则 LEFT1RIGHT3。****

利用工具排查死锁问题

在 Linux 下,可以使用 pstack + gdb 工具来定位死锁问题。

pstack命令可以显示每个线程的栈跟踪信息(函数调用过程),它的使用方式也很简单,只需要 pstack <pid>就可以了。

那么,在定位死锁问题时,我们可以多次执行 pstack 命令查看线程的函数调用过程,多次对比结果,确认哪几个线程一直没有变化,且是因为在等待锁,那么大概率是由于死锁问题导致的。