首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ReaderWriterLockSlim LockRecursionPolicy.SupportsRecursion DeadLock

ReaderWriterLockSlim LockRecursionPolicy.SupportsRecursion DeadLock
EN

Stack Overflow用户
提问于 2016-06-09 08:23:53
回答 1查看 1.6K关注 0票数 3

我有一个数据库写入的行动队列,由一个专门的线程管理。我有很多线程可以随时从数据库读取。

我使用ReaderWriterLockSlim进行读写访问控制。

我的问题是-为什么不推荐LockRecursionPolicy.SupportsRecursion?MSDN文档说:

不建议在新开发中使用递归,因为它会带来不必要的复杂性,并使您的代码更容易陷入死锁。

如何才能在这里实现僵局?例如,如果我尝试调用EnterReadLock时,WriteReadLock已经获得(而且我在SupportsRecursion策略下),我会得到一个异常.

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-06-09 08:54:37

锁递归是指在同一个线程上多次使用相同的锁,而不保留原来的锁。

这方面的主要问题是,首先要处理这种情况,您可能会遇到严重的问题,需要由谁来处理所需的同步--您的锁可能太细,或者太全局。多线程是困难的,使它更加困难是完全愚蠢的。

第二个大问题是锁被绑在线程上。但是,如果您正在编写异步代码,您的代码可能会随意地在不同的线程之间跳跃--这可能意味着似乎正在接受递归锁的代码没有--外部锁最终被一个不同于内部锁的线程所拥有,并且您永远与线程A陷入僵局,等待线程B完成,而B正在等待A释放外部锁。

您提到过,即使启用了递归,ReaderWriterLockSlim也会抛出许多递归异常。是的,这意味着使用递归锁比处理例如ReaderWriterLockMonitor时稍微安全一些。这些规则在MSDN中有明确的概述:

对于允许递归的ReaderWriterLockSlim,可以对线程可以进入的模式进行如下说明:

  • 处于读模式的线程可以递归地进入读模式,但不能进入写入模式或可升级模式。如果它尝试这样做,就会抛出一个LockRecursionException。进入读模式然后进入写入模式或可升级模式是一种死锁概率很高的模式,因此不允许使用。如前所述,在需要升级锁的情况下,提供了可升级模式。
  • 处于可升级模式的线程可以进入写入模式和/或读取模式,并且可以递归地进入这三种模式中的任何一种。但是,如果在读模式中有其他线程,则尝试进入写模式阻塞。
  • 处于写入模式的线程可以进入读模式和/或可升级模式,并且可以递归地进入这三种模式中的任何一种。
  • 没有进入锁的线程可以进入任何模式。此尝试可以基于与尝试输入非递归锁相同的原因而阻止。

一个线程可以以任何顺序退出它所输入的模式,只要它退出每种模式的次数与它进入该模式的次数相同。如果一个线程试图退出模式太多次,或者退出它尚未进入的模式,则会引发SynchronizationLockException。

他们尽了最大的努力完全不允许递归,这几乎保证会导致死锁。然而,这并不意味着仍然没有不被注意到的死锁(毕竟,您不需要递归来导致死锁--它只是给您提供了大量寻找死锁的机会)。更不用说在代码中经常递归其锁的任何一致性保证都是相当困难的--这可能意味着某些操作在从外部锁调用时是(半)原子的,但当它们被直接调用时就停止了。

多线程已经足够困难了。不要仅仅因为你的对象设计被破坏了就让它变得更加困难:)对多线程的一个很好的介绍(通常,特别是在.NET中)是Joe的“C#中的线程”,免费提供(谢谢,Joe!)。尤其是ReaderWriterLockSlim是在Locks中处理的

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37720533

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档