Класс OneManyLock
Я создал собственную конструкцию чтения-записи, работающую быстрее, чем
встроенный в FCL класс
ReaderWriterLockSlim
1
. Эта конструкция называется
1
Код в файле Ch30-1-HybridThreadSync.cs является частью сопроводительного кода
к данной книге. Вы можете загрузить его с сайта http://Wintellect.com/Books.
869
Гибридные.конструкции.в.FCL
OneManyLock
, так как она предоставляет доступ либо одному пишущему потоку, либо
нескольким читающим. Данный класс выглядит примерно следующим образом:
public sealed class OneManyLock : IDisposable {
public OneManyLock();
public void Dispose();
public void Enter(Boolean exclusive);
public void Leave();
}
Теперь посмотрим, как это работает. Класс содержит поле типа
Int32
, предна-
значенное для хранения состояния блокирования, объект
Semaphore
, блокирующий
читающие потоки, и объект
AutoResetEvent
, блокирующий пишущие потоки. Поле
записи состояния содержит в себе пять вложенных полей.
Четыре бита представляют состояние блокировки. Значение 0 означает
Free
(до-
ступно), 1 —
OwnedByWriter
(занято записывающим потоком), 2 —
OwnedByReaders
(занято читающими потоками), 3 —
OwnedByReadersAndWriterPending
(занято
записывающим и читающими потоками) и 4 —
ReservedForWriter
(зарезерви-
ровано для записывающего потока). Другие значения не используются.
Двадцать битов (число от 0 до 1048575) представляют количество потоков чтения
(RR), допустимых для блокировки.
Двадцать битов представляют количество потоков чтения (RW), ожидающих
получения блокировки. Эти потоки удерживает объект
AutoResetEvent
.
Двадцать битов представляют количество потоков записи (WW), ожидающих
получения блокировки. Эти потоки удерживает объект
Semaphore
.
Теперь, когда вся информация о блокировании сконцентрирована в одном поле
типа
Int64
, я могу управлять этим полем при помощи методов класса
Interlocked
.
В результате блокирование выполняется очень быстро и приводит к блокированию
потока только при конкуренции потоков.
Вот что происходит при входе потока в код блокирования совместного досту-
па:
Если блокирование возможно, присваиваем состоянию значение
OwnedByReaders
,
выполняем
RR = 1
, возвращаем управление.
Если состояние блокирования имеет значение
OwnedByReaders
(занято потоком
чтения), выполняем
RR++
, возвращаем управление.
В противном случае выполняем
RW++
, блокируем поток чтения. Когда поток
проснется, проходим цикл и делаем вторую попытку.
Вот что происходит при выходе потока из кода блокировки совместного до-
ступа:
Выполняем
RR--
.
870
Do'stlaringiz bilan baham: |