C# &引用;“重新实施”;(克隆)ReaderWriterLockSlim

C# &引用;“重新实施”;(克隆)ReaderWriterLockSlim,c#,multithreading,locking,readerwriterlockslim,C#,Multithreading,Locking,Readerwriterlockslim,我们的web应用程序中有几个完整的锁-s,如果用读写器锁替换它们,它们的性能可能会更高-即使有额外的RW锁开销,我们的代码也会更并行。不幸的是,我无法使用它,因为它似乎是一个相当大的同步错误,可能会导致某些硬件上的死锁。非常详细地解释了这个问题 上述问题似乎已在.NET Framework 4.0.30319.33440中得到修复,但并非所有Windows server版本都得到此修复。Windows 8.1和Windows Server 2012 R2具有修复程序。Windows Server

我们的web应用程序中有几个完整的
-s,如果用读写器锁替换它们,它们的性能可能会更高-即使有额外的RW锁开销,我们的代码也会更并行。不幸的是,我无法使用它,因为它似乎是一个相当大的同步错误,可能会导致某些硬件上的死锁。非常详细地解释了这个问题

上述问题似乎已在.NET Framework 4.0.30319.33440中得到修复,但并非所有Windows server版本都得到此修复。Windows 8.1和Windows Server 2012 R2具有修复程序。Windows Server 2012(不是R2)和Windows Server 2008 R2仍然存在该漏洞,即使在安装了最新补丁之后也是如此。看起来微软并没有计划在所有平台上解决这个问题

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

作为替代方案,我正在研究通过在System.Core中反编译代码并创建一个新类(类似于
MyrBlock
)来重新实现
ReaderWriterLockSlim
,该类具有一个(已知的)错误函数
ExitModule
。所有其他代码与原始的
ReaderWriterLockSlim
相同

这需要删除所有
\u DynamicallyInvokable
属性,并添加
System.Core
内部的2或3个类/结构。我完成了所有这些,并让新的锁类编译无误

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

或者:我(和链接文章)的理解是否错误?这个问题不需要首先解决吗?这篇文章的作者似乎做了一个非常详细的分析,在我看来这是正确的,但是微软没有将这一变化应用到某些Windows服务器版本上

如果您对此有任何想法,我们将不胜感激

编辑


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

这篇文章准确吗?我不知道。他们至少指出.NET中的更新解决了他们声称存在的问题,这表明它确实存在。另一方面,还有一个问题,那就是它是否适用于你。桌面x86机器对所有内存访问都有易失性语义,因此,如果唯一的bug描述的是缺少显式易失性操作,那么这在很大一部分硬件上都不会引起关注

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

当然,不管硬件架构如何,“volatile”对.NET编译器也有意义。在我看来,文章中引用的代码似乎不会受到编译器优化的影响,但我不是这方面的专家,所以我不能肯定

我从问题中得出结论,您并没有亲眼目睹这个bug的发生。在这一点上,这纯粹是一个假设

我会小心尝试重新实现这种类型的类,即使使用原始源代码作为起点

我的第一个选择是确保我已经升级到了一个足够新的.NET版本,您在文章中提到的bug已经修复

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

第三种选择是使用本机Win32“”结构(即通过p/invoke或C++/CLI)


只有当这些选项都不可行时,我才会不辞辛劳地实现我自己的读写器锁,而且你可以打赌我不会尝试“slim”变体(即,使用所有棘手的无锁功能…我可以看到使用一个volatile标志,但在其他情况下只使用传统的基于
监视器的代码).

如果将它们替换为读写器锁,性能可能会更高。

首先分析它是否值得更改。另外,对代码进行单元测试。确保更改这些方法不会导致任何其他操作中断。@L.B锁用于使某些操作原子化。这些操作涉及到网络流量,因此可以保证使用RW锁会更快。这些操作中有一半以上涉及读取远程服务器,但有些人试图写入它。@L.B它的设计不是很好,但现在改变它是不可行的-这些操作违背了一个不是为原子访问而设计的接口。@L.B我不是想暗示你不知道锁是什么。我只是说(或试图说)我们的线程做了很多事情