0x601 线程的死锁
死锁发生的时机
死锁通常发生在以下两种情况之一:
- 执行前锁定资源
- 执行过程过程中需求更多资源
执行之前锁定资源
在执行之前,如果线程尝试以不同的顺序锁定多个资源,死锁可能会发生。例如,线程A锁定资源1并尝试锁定资源2,同时线程B锁定资源2并尝试锁定资源1。如果每个线程在尝试锁定第二个资源之前不释放其已锁定的资源,它们将永远等待对方释放资源,导致死锁。
执行过程中获取更多资源
如果线程在执行过程中持有某些资源的锁,并尝试获取其他资源的锁,这也可能导致死锁,尤其是当其他线程持有这些额外资源的锁并且同样尝试获取第一线程所持资源的锁时。
死锁预防
死锁是指两个或两个以上的进程在执行过程中,由于资源竞争或者由于彼此通信而造成的一种阻塞现象,若无外力作用,它们都将无法推进下去。死锁的产生需要满足以下四个必要条件:
- 互斥条件:至少有一个资源必须处于非共享状态,即一次只能被一个进程或线程占用。
- 请求与保持条件:进程或线程至少需要持有一个资源,并且在等待其他资源时不释放已占有的资源。
- 不可剥夺条件:已分配给进程或线程的资源不能被强制性地剥夺,只能由持有资源的进程或线程主动释放。
- 循环等待条件:存在一个进程或线程的资源申请序列,使得每个进程或线程都在等待下一个进程或线程所持有的资源。
为了避免死锁的发生,可以采取以下几种方法: - 破坏互斥条件:对于某些资源,可以允许多个进程或线程同时访问,从而避免资源互斥。
- 破坏请求与保持条件:确保进程或线程在请求资源时不会持有其他资源。
- 破坏不可剥夺条件:允许系统或某个进程或线程剥夺其他进程或线程所持有的资源。
- 破坏循环等待条件:对系统中的资源进行编号,规定进程或线程只能按照编号递增的顺序申请资源,从而避免循环等待。
死锁避免
锁定资源前检测锁定后系统是否还处于安全状态。
死锁避免涉及操作系统在运行时动态地考虑资源分配请求,确保不会进入不安全状态(即可能导致死锁的状态)。著名的算法包括银行家算法,它在分配资源前检查分配后系统是否还处于安全状态。
死锁检测和恢复
操作系统可以定期检测死锁的存在,并在检测到死锁后采取措施解决。检测通常通过资源分配图等数据结构完成。一旦检测到死锁,系统可以采取以下一种或多种恢复措施:
- 终止一个或多个涉及死锁的进程;
- 从死锁进程中剥夺资源,并将资源分配给其他进程;
操作系统如何检测死锁
资源分配图/死锁检测算法
检测资源分配(线程1->资源A)后是否出现环路
银行家算法
超时检测
某个进程持有某个资源超出了时间阈值则认为该进程可能进入了死锁状态,并采取对应的措施。
资源分配策略
通过改进资源的分配策略,例如限制同时运行的线程数量或实现资源分配的优先级制度,也可以减少死锁的发生。
操作系统可能采用上述策略的组合来处理死锁问题。然而,在设计多线程应用程序时,最好的做法是尽量避免出现死锁的情况,通过 careful design and best practices in coding 如死锁预防和避免策略,以及合理的锁定和同步机制。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 程序员小航
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果