Глава.30 .Гибридные.конструкции.синхронизации.потоков
важно то, что поток очень быстро блокируется. Если теперь появится второй
поток и вызовет метод
Enter
, он увеличит значение поля
m_waiters
уже до двух
и обнаружит присутствие уже запертого потока, поэтому он блокируется, вызы-
вая метод
WaitOne
, использующий поле
AutoResetEvent
. Вызов метода
WaitOne
заставит поток перейти в ядро Windows, и именно эта процедура приводит
к значительному снижению производительности. Однако этот поток в любом
случае должен прекратить свою работу, поэтому тот факт, что полная остановка
требует лишних временных затрат, не является слишком критичным. В итоге
поток блокируется и перестает впустую расходовать процессорное время из-за
зацикливания. Именно для этого и нужен продемонстрированный еще в главе 29
метод
Enter
класса
SimpleSpinLock
.
Теперь перейдем к методу
Leave
. Его вызов потоком сопровождается вызовом
метода
Interlocked.Decrement
, вычитающего из поля
m_waiters
единицу. Ра-
венство этого поля нулю означает отсутствие заблокированных потоков внутри
вызова метода
Enter
, поэтому поток, который вызвал метод
Leave
, может просто
вернуть управление. И снова посмотрим, насколько быстро все это происходит.
Освобождение блокировки означает, что поток вычитает единицу из поля
Int32
,
выполняет быструю проверку условия и возвращает управление! В то же время,
если вызывающий метод
Leave
поток обнаруживает отличное от единицы значение
поля
m_waiters
, он узнает о наличии конкуренции и о том, что, по крайней мере,
один заблокированный поток в ядре уже имеется. Поток, вызывающий метод
Leave
,
должен разбудить один (и только один) из заблокированных потоков. Для этого он
вызывает метод
Set
объекта
AutoResetEvent
. Данная операция ведет к снижению
производительности, так как потоку приходится совершать переходы к ядру и обрат-
но. К счастью, подобный переход осуществляется только при наличии конкуренции.
Разумеется, объект
AutoResetEvent
гарантирует пробуждение только одного из
заблокированных потоков; все прочие заблокированные объектом
AutoResetEvent
потоки останутся в таком состоянии, пока новый незаблокированный поток не
вызовет метод
Leave
.
ПриМеЧание
В.действительности.метод.Leave.может.вызвать.любой.поток.в.любой.момент.
времени,.потому.что.метод.Enter.не.сохраняет.информацию.о.том,.какому.по-
току.удалось.успешно.запереться .Добавить.для.этого.поле.и.управляющий.код.
несложно,.но.это.увеличивает.объем.памяти,.необходимой.для.самого.объекта.
блокирования,.и.снижает.производительность.выполнения.методов.Enter.и.Leave,.
ведь.им.в.результате.приходится.работать.с.этим.новым.полем .Я.предпочитаю.
иметь.быстродействующее.блокирование.и.корректно.использующий.его.код .
С.информацией.подобного.рода.не.умеют.работать.ни.события,.ни.семафоры;.это.
могут.делать.только.мьютексы
Do'stlaringiz bilan baham: |