【问题标题】:Can lock ordering be enforced / detected to prevent deadlocks?可以强制/检测锁定顺序以防止死锁吗?
【发布时间】:2014-05-12 16:03:59
【问题描述】:

我继承了一个历史悠久的大项目,我的任务是修复多年来报告的一堆死锁。

我了解一些死锁的性质,并且可以使用一些精心布置的Sleeps 和其他强制计时来始终如一地重现它们。

但是,修复死锁并不是那么简单。该代码没有使用任何关于锁定资源的策略。我可以为每个死锁手动制定解决方案,但其中大部分归结为锁排序问题。

例如,工人 1:

Acquires resource A
{
  ...
  Acquires resource B
  {
    ...
  }
}

当工人 2 这样做时:

Acquires resource B
{
  ...
  Acquires resource A
  {
    ...
  }
}

所以我的问题是:在代码中检测和/或强制执行锁顺序问题的最佳方法是什么?静态分析?是否有一种编译时方法来检测这个(理想)?还是我必须在运行时检测这类问题?

感谢任何帮助。

【问题讨论】:

  • 静态死锁检测有一些研究课题,但最常用的技术是lock hierarchies
  • 我之前发现 petri 网在检测死锁方面非常有效
  • “学术”的方法是通过构建 DAG(例如 Helgrind 正在使用它)-“使用基于图的检测,如果你有一个正在积极等待的工人列表和一个worker 拥有什么资源,你可以构建一个谁在等待谁的图表。如果你这样做并在图表中检测到一个循环,则发生了死锁(除非循环中有人在超时计划中并且可能愿意打破死锁). 这是一个万无一失的策略,但在锁定获取的运行时影响方面可能代价高昂。” (msdn.microsoft.com/en-us/magazine/cc163618.aspx)

标签: c++ multithreading winapi visual-c++


【解决方案1】:

有一个简单的策略可以发现潜在的死锁。如果一位代码锁定 A,然后 B,而另一位代码锁定 B,然后 A,就会发生死锁。如果他们在错误的时间这样做,那就是死锁。如果他们在没有造成任何伤害的情况下这样做,这可能是一个潜在的僵局。假设第一个代码是正确的,那么第二个代码不应该尝试按该顺序使用锁(您必须确定哪个代码是错误的,哪个是正确的)。

为每个锁分配一个整数值。假设锁 A = 100,锁 B = 130。然后你制定一个规则:当持有一个值为 X 的锁时,只有当它的值 Y > X 时才必须获得另一个锁。代码锁定 B 然后 A 违反了条件。

显然,这需要对所有锁进行一些封装才能实际检查这一点。如果您发现违规,您必须决定是否更改代码或分配给锁的值,直到您停止发现潜在的死锁。

【讨论】:

  • 这是一个很酷的策略。我们正在使用自制的CriticalSection 对象,因此这应该很容易检测到不一致的顺序,甚至报告潜在的死锁情况以及哪些线程拥有哪些锁的当前状态......我仍在寻找编译时间方法虽然在我实现这个之前。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多