面试题答案
一键面试死锁产生的四个必要条件
- 互斥条件:资源在某一时刻只能被一个线程占用。
- 占有并等待条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放。
- 不可剥夺条件:线程已获得的资源,在未使用完之前,不能被其他线程强行剥夺,只能由该线程自己释放。
- 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。
预防死锁的方法
- 破坏互斥条件:尽量使用可共享的资源,避免独占资源。但有些资源本身特性决定其只能互斥访问,此方法应用场景有限。
- 破坏占有并等待条件:在进程开始运行前,一次性分配它所需要的所有资源;或者在申请新资源时,先释放已占有的资源。
- 破坏不可剥夺条件:当一个线程占有某些资源又申请新资源得不到满足时,必须释放已经占有的资源,待以后需要时再重新申请。
- 破坏循环等待条件:对资源进行编号,规定线程申请资源时必须按照编号从小到大的顺序申请,这样可以避免循环等待。
死锁排查策略与工具
- 策略:
- 日志分析:在关键的加锁和解锁位置添加日志,记录线程ID、资源ID以及加锁解锁时间等信息,通过分析日志找出死锁发生的线索。
- 资源分配图算法:构建资源分配图,通过算法检测图中是否存在环路,若存在环路则可能存在死锁。
- 工具:
- pthread库自带工具:在Linux下,使用
pthread_mutexattr_settype
设置互斥锁类型为PTHREAD_MUTEX_ERRORCHECK
,这样当线程试图重复锁定同一互斥锁时,会返回错误,有助于发现死锁。 - GDB调试:使用GDB的
info threads
查看所有线程状态,thread <thread_id>
切换到指定线程,bt
查看线程堆栈信息,通过分析线程堆栈找到死锁相关代码。 - Valgrind:它能检测出许多内存相关问题,也可用于发现死锁。运行程序时,Valgrind会报告死锁相关信息。
- pthread库自带工具:在Linux下,使用