我一直在使用ReaderWriterLockSlim一段时间,它已经满足了我的需求。当我继续微调我的应用程序时,我发现ReaderWriterLockSlim
对我的用例来说稍微不太理想。根据文档(以及我的经验),它支持作者优先于读者(即当读者和作者排队时,作者将获得偏好)。但是,我需要一个有利于读者的等价物。我理解这种组件的副作用(特别是作者饥饿问题)。是否有ReaderWriterLockSlim等价于读者?
有人可以指出任何生产就绪等价物吗?谢谢。
我一直在使用ReaderWriterLockSlim一段时间,它已经满足了我的需求。当我继续微调我的应用程序时,我发现ReaderWriterLockSlim
对我的用例来说稍微不太理想。根据文档(以及我的经验),它支持作者优先于读者(即当读者和作者排队时,作者将获得偏好)。但是,我需要一个有利于读者的等价物。我理解这种组件的副作用(特别是作者饥饿问题)。是否有ReaderWriterLockSlim等价于读者?
有人可以指出任何生产就绪等价物吗?谢谢。
根据MSDN,ReaderWriterLockSlim青睐作家。这意味着,当有读者和作者排队时,作家会获得偏好。
这会产生读者饥饿,测试代码重现这是here。 我认为饥饿只有在写入是一个长操作时才会发生,涉及线程上下文切换。至少它总是在我的机器上复制,所以请告诉我,如果我错了。
另一方面,来自.NET 2.0的ReaderWriterLock不会以牺牲性能为代价来产生读取器或写入器饥饿。 Here是以前样本的修改代码,以显示没有饥饿发生。
所以,回到你的问题 - 这取决于你需要什么功能从RW锁。 递归锁,异常处理,超时 - 最接近匹配生产质量支持以上所有内容的RW锁,并支持读者可能是ReaderWriterLock。
此外,您可以采用描述first readers-writers problem的wiki文章中的代码,但当然您需要手动实现上述所有必需的功能,并且实现将具有writer-starvation问题。
锁芯也许可以是这样的:
class AutoDispose : IDisposable
{
Action _action;
public AutoDispose(Action action)
{
_action = action;
}
public void Dispose()
{
_action();
}
}
class Lock
{
SemaphoreSlim wrt = new SemaphoreSlim(1);
int readcount=0;
public IDisposable WriteLock()
{
wrt.Wait();
return new AutoDispose(() => wrt.Release());
}
public IDisposable ReadLock()
{
if (Interlocked.Increment(ref readcount) == 1)
wrt.Wait();
return new AutoDispose(() =>
{
if (Interlocked.Decrement(ref readcount) == 0)
wrt.Release();
});
}
}
比较3个实现性能,采用3读卡器和3个写线程,使用简单的内存操作(使用长阻塞操作会产生读者饥饿RWLockSlim和作家饥饿自定义锁):
我确信,工作量循环不被编译器展开,但也可能有其他陷阱我不知道的,因此T用一粒盐做这些测量。测试的源代码是here。
很好很详细的答案!非常感谢 - 我会看看。 –
无法确切地证明代码的缺失。但是,不,这是不太可能的。请避免提出购物问题。 –
如果你想支持读取,为什么不用一个更新的克隆替换内部列表?您的代码将被锁定,但更新时会稍重一些。 – jgauffin
是的,这听起来像你可以用jgauffin所建议的副本来解决这个问题,或者如果数据结构对于廉价的副本来说太大了,那么写入缓冲区的写入就不那么频繁。然后,您可以通过上下调整缓冲区的刷新时间来调整读/写余额。 –