"重新实现" (克隆)ReaderWriterLockSlim

时间:2014-10-23 20:03:35

标签: c# multithreading locking readerwriterlockslim

我们的Web应用程序中有几个完整的lock - 如果用读写锁替换它们可能会更高效 - 即使有RW锁的额外开销,我们的代码也会更加平行。不幸的是,我不能使用ReaderWriterLockSlim因为看起来像是一个非常大的同步错误,可能会导致某些硬件死锁。 This article非常详细地解释了这个问题。

上述问题似乎在.NET Framework 4.0.30319.33440中得到修复,但并非所有Windows服务器版本都能获得此修复程序。 Windows 8.1和Windows Server 2012 R2具有此修复程序。即使在最新的补丁之后,Windows Server 2012(不是R2)和Windows Server 2008 R2仍然存在错误。看起来微软并不打算在所有平台上解决这个问题。

我们的各种服务器环境使用不同版本的Windows Server,我已经确认某些服务器有修复,而有些服务器没有。这意味着我无法安全地将所有lock语句更改为读写器锁,因为在我们的某些服务器上,应用程序可能会随机死锁。

作为替代方案,我正在考虑通过反编译System.Core中的代码并创建一个具有一个(已知)buggy函数的新类(类似ReaderWriterLockSlim)来重新实现MyRWLock { {1}}已修复。所有其他代码与原始ExitMyLock相同。

这需要删除所有ReaderWriterLockSlim属性,并添加__DynamicallyInvokable内部的2或3个类/结构。我做了所有这些并且新的锁类编译没有错误。

我的问题是:有人能想到这个新课程不能像原来的System.Core课那样工作的原因吗?我认为自己在线程方面相当不错,但我不是专家。由于我没有更改任何代码(除了修复某些类型名称以指向新的ReaderWriterLockSlim而不是MyRWLock和属性),我相信这应该有效。但是,我确实想知道,如果我忘记了一些可能以各种有趣的方式打破这个难以调试的东西。

或者:我的(和链接文章)理解错了吗?这个问题首先不需要修复吗?该文章的作者似乎做了一个非常详细的分析,看起来对我来说是正确的,但微软没有将更改应用于某些Windows Server版本。

对此的任何想法都将非常感激。

修改

要为完整锁添加更多上下文,以下是它们的用途。我们有一项服务,在执行其工作时读取/写入远程服务。读取比写入多得多。读取涉及1个网络往返,写入涉及到远程服务的3个网络往返。当写入发生时,不会发生读取(写入实际上是读取> delete-> add)。现在,我们在所有这些操作中使用完整的ReaderWriterLockSlim - s,但这意味着所有尝试读取的线程仍然必须排队,直到当前读取完成,即使没有写入。在我看来,RW锁是理想的选择。

1 个答案:

答案 0 :(得分:1)

文章准确吗?我不知道。他们至少指向.NET中的更新来解决他们声称存在的问题,所以这表明它是。另一方面,还有一个问题是它是否适用于你。无论如何,桌面x86机器都具有针对所有内存访问的易失性语义,因此如果唯一的错误描述的是缺少显式的易失性操作,那么就不会对那里的大部分硬件产生担忧。

在大型服务器硬件上,架构是不同的,它们可能具有不同的语义,需要明确的易失性操作。这可能是你想要研究的东西。

当然,无论硬件架构如何," volatile"对.NET编译器也有意义。文章中引用的代码在我看来并不像它会受到编译器优化的影响,但我不是该领域的专家,所以我无法肯定地说。

我从你没有亲眼目睹过这个错误的问题中得到它。在这一点上,这只是一个纯粹的假设问题。

我会谨慎地尝试重新实现这种类型的类,即使使用原始源作为起点。

我的第一选择是确保我已升级到最近的.NET版本,以及您引用的文章中描述的错误已修复。

第二种选择是使用普通的ReaderWriterLock类而不是ReaderWriterLockSlim。

第三种选择是使用原生的Win32" slim reader/writer lock"结构(即通过p / invoke或C ++ / CLI)。

只有当这些选项都没有被证明是可行的时候我才会麻烦地实现我自己的读写器锁,你可以打赌我不会尝试" slim"变种(即具有所有棘手的无锁的东西......我可以看到使用一个易失性标记,但是只是坚持使用传统的基于Monitor的代码)。