Ответ 1
Согласно MSDN, ReaderWriterLockSlim поддерживает авторов. Это означает, что когда в очереди появятся читатели и писатели, писатели получат предпочтение.
Это может вызвать голод читателя, тестовый код для воспроизведения этого здесь. Я предполагаю, что голодание может произойти только в том случае, если запись является длительной операцией, включающей переключатель контекста потока. По крайней мере, он всегда воспроизводится на моей машине, поэтому, пожалуйста, скажите мне, если я ошибаюсь.
С другой стороны, ReaderWriterLock от .net 2.0 не производит ни чтения, ни голода писателя, за счет снижения производительности. Здесь изменен код из предыдущего образца, чтобы показать, что голодания не происходит.
Итак, вернемся к вашему вопросу - это зависит от того, какие функции вы требуете от блокировки 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 и головоломка-писателя для пользовательской блокировки):
Я убедился, что компилятор не разворачивает цикл рабочей нагрузки, но могут быть другие ошибки, о которых я не знаю, поэтому сделайте эти измерения с помощью соли. Исходный код для тестов здесь.