面试题答案
一键面试可能出现死锁的场景
假设有两个线程 Thread A
和 Thread B
,以及两种资源 Resource X
和 Resource Y
。
Thread A
先获取Resource X
,然后尝试获取Resource Y
。Thread B
先获取Resource Y
,然后尝试获取Resource X
。 此时,如果Thread A
持有Resource X
且未释放,Thread B
持有Resource Y
且未释放,双方都在等待对方释放自己所需的资源,就会发生死锁。
通过资源分配图算法检测死锁
- 资源分配图的构建:
- 每个线程作为一个节点(用圆表示)。
- 每个资源类型作为一个节点(用方框表示,方框内的小点表示该资源类型的实例数)。
- 从线程到资源的边表示线程请求该资源(请求边)。
- 从资源到线程的边表示资源已分配给该线程(分配边)。
- 算法步骤:
- 寻找一个没有请求边的线程节点(即该线程已获得所有所需资源)。
- 移除该线程节点及其所有分配边,这相当于该线程完成任务并释放资源。
- 重复上述步骤,如果最终能移除所有线程节点,则系统无死锁;否则,存在死锁。
避免死锁的方法
- 资源分配顺序法:
- 为所有资源类型定义一个全局的排序。
- 每个线程按照这个顺序请求资源,例如先请求资源
A
,再请求资源B
,最后请求资源C
。这样就不会出现循环等待的情况,从而避免死锁。
- 银行家算法:
- 系统需要知道每个线程对每种资源的最大需求量(
Max
)、当前已分配的资源量(Allocation
)以及系统当前可用的资源量(Available
)。 - 当一个线程请求资源时,系统检查该请求是否会导致系统进入不安全状态。如果不会,才分配资源;否则拒绝请求。具体步骤如下:
- 假设分配资源给请求线程,更新
Available
、Allocation
矩阵。 - 检查是否存在一个安全序列,即是否能找到一种线程执行顺序,使得每个线程都能获取所需资源并完成任务,释放其占有的资源。如果存在,则分配是安全的;否则拒绝请求。
- 假设分配资源给请求线程,更新
- 系统需要知道每个线程对每种资源的最大需求量(