4-28.【OC】【锁】请画出“双锁反序”死锁的 wait-for graph。

6 阅读1分钟

“双锁反序”(AB-BA Deadlock)是多线程开发中最经典的死锁模型。当两个线程以相反的顺序请求两把相同的锁时,就会形成环路等待。

1. 场景描述

  • 线程 1:已经持有 锁 A,正在尝试获取 锁 B
  • 线程 2:已经持有 锁 B,正在尝试获取 锁 A

2. Wait-for Graph (等待图)

在等待图中,节点代表线程,有向边代表等待关系

  • 节点 T1:代表线程 1。
  • 节点 T2:代表线程 2。
  • 边 T1 -> T2:表示 T1 正在等待 T2 释放资源(锁 B)。
  • 边 T2 -> T1:表示 T2 正在等待 T1 释放资源(锁 A)。

结论:图中出现了一个闭环(Cycle) ,这是死锁存在的充分必要条件。


3. 资源分配图 (Resource Allocation Graph)

为了更清晰地看到“锁”在其中的位置,我们可以使用资源分配图。

  • 持有关系(Solid Line) :锁 A -> 线程 1,锁 B -> 线程 2。
  • 请求关系(Dashed Line) :线程 1 -> 锁 B,线程 2 -> 锁 A。

4. 如何在代码中规避?

针对这种死锁,通常有三种修复策略:

  1. 固定加锁顺序:强制所有线程必须先获取 A 再获取 B。
  2. 使用 tryLock:如果获取第二把锁失败,则主动释放已持有的第一把锁,回退重试,破坏“不可剥夺”条件。
  3. 合并锁:如果 A 和 B 总是同时被使用,考虑将它们合并为一个更大粒度的锁。

在您之前提到的 Objective-C Runtime 内部,为了防止这类死锁,苹果工程师在源码中对 runtimeLockcacheUpdateLock 的获取顺序有着极其严格的规定。