16

我使用ReaderWriterLockSlim已经有一段时间了,到目前为止它已经满足了我的需求。当我继续微调我的应用程序时,我发现这ReaderWriterLockSlim对于我的用例来说不是最理想的。

根据文档(和我的经验),它有利于作者而不是读者(即当读者和作者排队时,作者将获得优先权)。但是,我需要一个有利于读者的等价物。我了解此类组件的副作用(特别是作家饥饿问题)。

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

4

1 回答 1

7

根据 MSDN,ReaderWriterLockSlim 偏爱作家。这意味着当队列中有读者和作者时,作者将获得优先权。

这会产生读者饥饿,测试代码重现这个是here。我假设只有在写入是一个涉及线程上下文切换的长操作时才会发生饥饿。至少它总是在我的机器上复制,所以如果我错了,请告诉我。

另一方面,.net 2.0 中的 ReaderWriterLock 不会产生读取器或写入器饥饿,但会降低性能。是上一个示例中的修改代码,以表明没有发生饥饿。

因此,回到您的问题 - 这取决于您需要 RW 锁的哪些功能。递归锁、异常处理、超时 - 最接近支持上述所有内容的生产质量RW 锁,并且有利于读者的可能是 ReaderWriterLock。

您也可以采用描述第一个读者-作者问题的 wiki 文章中的代码,但当然您需要手动实现上述所有必需的功能,并且实现会有写者饥饿问题。

锁芯可能看起来像这样:

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 的读取器饥饿和自定义锁的写入器饥饿):

性能比较

我确保编译器不会展开工作负载循环,但可能还有其他我不知道的陷阱,所以对这些测量持保留态度。测试的源代码在这里

于 2013-04-11T09:08:37.617 回答