根据MSDN,ReaderWriterLockSlim偏向于写入者。这意味着当读取者和写入者在队列中时,写入者将获得优先权。
这可能会导致读取者饥饿,用于重现的测试代码在
此处。
我认为只有在写入是涉及线程上下文切换的长时间操作时才会发生饥饿。至少在我的机器上总是重现,所以如果我错了,请告诉我。
另一方面,来自.net 2.0的ReaderWriterLock既不会产生读取者饥饿,也不会产生写入者饥饿,代价是性能降低。
这里是修改后的代码,展示没有发生饥饿。
因此,回到您的问题-这取决于您从RW锁中需要哪些功能。递归锁定、异常处理、超时-最接近
生产质量的RW锁,支持所有上述功能,并偏向于读取者,可能是ReaderWriterLock。
您可以采用维基文章描述的第一个读写问题中的代码,但是您需要手动实现上述所有所需功能,并且实现将会出现写者饥饿问题。
锁核心可能看起来像这样:
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](https://istack.dev59.com/I2BRG.webp)
我确保编译器没有展开工作负载循环,但可能存在我不知道的其他陷阱,因此这些测量结果仅供参考。测试的源代码在这里。