【问题标题】:Ordered Locking Pattern and ReaderWriterLock in C#C# 中的有序锁定模式和 ReaderWriterLock
【发布时间】:2011-01-20 17:16:11
【问题描述】:

当与 ReaderWriterLock(或 ReaderWriterLockSlim)一起使用时,有序锁定模式是否可以防止死锁?

很明显,该模式可以防止使用互斥锁的死锁。如果我用((N 个带读锁的资源)和(1 个或 2 个带写锁的资源))锁定多个资源,它是否仍然可以防止死锁。

例如:(粗体数字代表有写锁的资源)

1 2 3 4 5

2 3 4

1 4 5

【问题讨论】:

  • 澄清一下,您是在问是否可以使用 ReaderWriterLock 来实现 Ordered Locking 模式?

标签: c# multithreading locking readerwriterlock


【解决方案1】:

tl;dr 资源排序也可以防止读写锁死锁。

长答案:

像这样画一个等待图:

首先为所有资源从左到右画一个顶点 规定的顺序。

然后,对于每一个等待资源的进程,绘制一个顶点, 紧接在等待资源的顶点之前。 如果进程没有等待任何资源,则绘制一个顶点 在最右边,在所有资源顶点之后。

然后从每个进程到它所在的资源绘制一条边 进程正在等待并从每个资源到 当前持有该资源的进程。

考虑图上的每条边。有两种情况:

  • 边缘是Pi -> Ri,即从进程到资源。由于每个 进程只在等待一个资源,我们已经绘制了 进程的顶点紧邻它所在的资源的左侧 等待,则边缘从左到右。

  • 边缘是Ri -> Pj,即从资源到进程。如果Pj 是 不等待任何资源,则其顶点在右侧 所有资源,因此边缘从左到右。如果Pj 正在等待Rk,然后是i < k,因为进程在 命令。如果i < k,那么RiRk的左边,而Pj在 紧邻Rk 的左侧(因为我们是这样绘制图形的), 因此RiPj 的左侧,因此边缘再次留给 对。

由于以这种方式绘制的图形的所有边都是从左到 对了,那么我们就构造了图的拓扑排序, 因此该图没有循环,因此不会发生死锁。

请注意,重要的是进程等待的事实,而不是为什么等待 等待。因此,无论是否等待互斥体, 读写锁,信号量或其他 - 这种死锁策略 预防对所有人有用。

【讨论】:

  • 谢谢!我已经通过大量使用实验“证明”了它,但我一直有一些挥之不去的疑问。
【解决方案2】:

我认为您的 Ordered 锁定模式是错误的,您必须按顺序获取 所有 锁。要抢“4”的写锁,首先需要抢“3”的写锁。对于“5”,您需要获取“3”“4”“5”的写锁。

对于普通锁,有序锁模式很昂贵,但是对于 SRW 锁,它们是超级昂贵的,因为你必须先扔掉所有的读者。请记住,仅当您的至少 80% 以上的访问不需要写入锁时,SRW 锁才有优势 - 否则它会非常昂贵,而且您可以使用简单的锁做得更好。

更好的是,尝试将您的代码解耦,这样您就不需要有序锁定(即,我不需要同时访问“3”和“4”的数据)。这并不总是可行的,但您越能做到这一点,您的代码就会越简单。

【讨论】:

    【解决方案3】:

    我尝试在 C# 中实现有序锁,以检查是否已按固定顺序获取锁。见http://www.codeproject.com/Tips/563154/OrderedLock-in-Csharp

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 2012-11-14
      • 2012-11-14
      • 1970-01-01
      • 1970-01-01
      • 2012-02-29
      • 1970-01-01
      相关资源
      最近更新 更多