读写器锁定Slim锁定递归策略.支持重新启动锁定



我有一个数据库写入操作队列,由一个专用线程管理。我有很多线程可以随时从数据库中读取。

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

我的问题是——为什么锁定递归策略。支持不建议重新报告?MSDN文档说:

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

如何在此处实现死锁?例如,如果我试图在WriteReadLock已经获取时调用EnterReadLock(并且我在SupportsRegistration策略下),我会得到一个异常。。。

锁递归是指在同一个线程上多次使用同一个锁,而不离开原始锁。

这样做的主要问题是,首先要遇到这种情况,您可能会在谁处理必要的同步方面遇到严重问题——您的锁可能过于精细,或者过于全局。多线程很难,让它变得更难完全是愚蠢的。

第二件大事是锁与线程绑定。然而,如果你在写异步代码,你的代码可能会随意地在不同的线程之间跳转,这可能意味着看起来采用递归锁的代码不是-外部锁最终由与内部锁不同的线程拥有,并且你永远与线程a僵持不下,等待线程B完成,而B正在等待A释放外部锁定。

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

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

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

线程可以按任何顺序退出其已进入的模式,只要它退出每个模式的次数与进入该模式的次数完全相同。如果线程多次尝试退出某个模式,或退出未进入的模式,则会引发SynchronizationLockException。

他们尽了最大努力彻底禁止递归,这几乎可以保证会导致死锁。然而,这并不意味着仍然没有被忽视的死锁(毕竟,你不需要递归来导致死锁——它只是给了你很多很难找到的死锁机会)。更不用说,在常规递归锁的代码中很难保证一致性——这可能意味着,当从外部锁调用某些操作时,它们是(半)原子的,但当它们被直接调用时,它们就不再是了。

多线程已经够难的了。不要因为你的对象设计坏了就让它变得更难:)多线程的一个很好的介绍(一般来说,尤其是在.NET中)是Joe Albahari的"C#中的线程",可以在互联网上免费获得(谢谢,Joe!)。ReaderWriterLockSlim在http://www.albahari.com/threading/part4.aspx#_Reader_Writer_Locks

最新更新