2013-01-14 50 views
16

我一直在使用ReaderWriterLockSlim一段时间,它已经满足了我的需求。当我继续微调我的应用程序时,我发现ReaderWriterLockSlim对我的用例来说稍微不太理想。根据文档(以及我的经验),它支持作者优先于读者(即当读者和作者排队时,作者将获得偏好)。但是,我需要一个有利于读者的等价物。我理解这种组件的副作用(特别是作者饥饿问题)。是否有ReaderWriterLockSlim等价于读者?

有人可以指出任何生产就绪等价物吗?谢谢。

+3

无法确切地证明代码的缺失。但是,不,这是不太可能的。请避免提出购物问题。 –

+0

如果你想支持读取,为什么不用一个更新的克隆替换内部列表?您的代码将被锁定,但更新时会稍重一些。 – jgauffin

+1

是的,这听起来像你可以用jgauffin所建议的副本来解决这个问题,或者如果数据结构对于廉价的副本来说太大了,那么写入缓冲区的写入就不那么频繁。然后,您可以通过上下调整缓冲区的刷新时间来调整读/写余额。 –

回答

6

根据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和作家饥饿自定义锁):

Performance comparison

我确信,工作量循环不被编译器展开,但也可能有其他陷阱我不知道的,因此T用一粒盐做这些测量。测试的源代码是here

+0

很好很详细的答案!非常感谢 - 我会看看。 –

相关问题