Здравствуйте, Aviator, Вы писали:
A>Интересует архитектура, реализация и примеры использования
Пример использования — там, где затраты на блокировки несоизмеримо малы с затратами целевых операций чтения/записи. Особенно удачно его применение в тех случаях, где информацию чаще читают, нежели изменяют. Справочные данные — идеальный пример.
Кратко устройство:
Есть 2 очереди — читателей и писателей. Пока очередь писателей пуста допускаем читателей. Как только в очереди писателей появился хоть кто-то, прекращаем допуск читателей, накапливаем их в очереди читателей. Ждем, пока все читатели освободят ресурс, после этого запускаем одного писателя. После покидания писателем ресурса запускаем всех читателей из очереди читателей. Goto begin.
Т.е. поочередно запускаем писателя/читателей.
Реализации могут быть разные. Самое простое — это интерфейс запросов ресурса с блокирующими методами. Использовать типа так:
swmrLock.EnterReader();
try {
...
} finally {
swmrLock.ExitReader();
}
Аналогично Enter/ExitWriter. Эта схема самая распространенная.
Недостаток схемы в том, что никто нам не запрещает обратиться к ресурсу напрямую в обход схемы синхронизации. Однако, в случае, где детали обращения к ресурсу скрыты инкапсуляцией, такая схема вполне имеет право на жизнь.
В публичных интерфейсах можно поступить более надежным способом — это предоставить 2 различных интерфейса для доступа к ресурсу:
// ReadOnly
public interface IReadInterface1 : IDisposable {
int SomeAspect { get; }
}
// Common Read/Write
public interface IInterface1 : IReadInterface {
int SomeAspect { get; set; }
}
public interface ISomeRootObj {
IInerface1 Resource1 { get; }
IReadInterface1 ReadResource1 { get; }
IInerface12 Resource2 { get; }
IReadInterface2 ReadResource2 { get; }
}
Соответственно, реализовать в этой схеме допуск "унутренними" резервами, скрыв подробности и не дав возможности "обходного пути".