C# &引用;“重新实施”;(克隆)ReaderWriterLockSlim
我们的web应用程序中有几个完整的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
锁
-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我不是想暗示你不知道锁是什么。我只是说(或试图说)我们的线程做了很多事情