概念
死锁指的是两个或多个线程彼此等待对方释放所持有的资源,从而导致所有线程都无法继续执行,程序无法继续运行的情况。
- 死锁是一种静止状态,线程被无限阻塞,直到外部干预,如强制终止某些线程。
- 死锁发生时,线程无法自行解锁,需要外部的干预来打破循环依赖,释放资源以解决死锁。
产生死锁的原因
- 系统资源不足。
- 进程运行推进的顺序不合适。
- 资源分配不当。
死锁四个必要条件
- 互斥:进程对已分配的资源独享,其他进程需要等待。
- 请求保持:进程需要持有已分配的资源,并继续请求其他资源,但他们无法满足请求,导致进程阻塞并保持对已有资源的持有。
- 不可剥夺:进程已经获得的资源不能被其他进程强制性剥夺。
- 环路等待:存在多个进程之间形成循环等待资源的关系。
死锁预防
- 破坏互斥条件:尽可能地共享资源,而不是互斥地独占资源。
- 破坏请求保持条件:请求资源时先释放已占有的资源,再请求所需的资源,以避免持有资源的阻塞情况。
- 破坏不可剥夺条件:引入资源抢占机制,使得系统可以对进程已获取的资源进行剥夺。
- 破坏环路等待条件:通过有序资源分配策略,避免形成循环等待的资源关系。
哲学家就餐问题
银行家算法-预测资源需求
一个数组 state
来记录每一位哲学家在进程、思考还是饥饿状态(正在试图拿叉子)。
那么,一个哲学家只有在两个邻居都没有进餐时,才可以进入进餐状态。
第i
个哲学家的左邻右舍,则由宏 LEFT
和 RIGHT
定义:LEFT : ( i + 5 - 1 ) % 5 RIGHT : ( i + 1 ) % 5
比如 i
为 2
,则 LEFT
为 1
,RIGHT
为 3
。****
利用工具排查死锁问题
在 Linux 下,可以使用
pstack + gdb
工具来定位死锁问题。
pstack
命令可以显示每个线程的栈跟踪信息(函数调用过程),它的使用方式也很简单,只需要 pstack <pid>
就可以了。
那么,在定位死锁问题时,我们可以多次执行 pstack 命令查看线程的函数调用过程,多次对比结果,确认哪几个线程一直没有变化,且是因为在等待锁,那么大概率是由于死锁问题导致的。