Простая гибридная блокировка
Начнем с демонстрации примера гибридной блокировки в рамках синхронизации
потоков:
internal sealed class SimpleHybridLock : IDisposable {
// Int32 используется примитивными конструкциями
855
Простая.гибридная.блокировка
// пользовательского режима (Interlocked-методы)
private Int32 m_waiters = 0;
// AutoResetEvent - примитивная конструкция режима ядра
private AutoResetEvent m_waiterLock = new AutoResetEvent(false);
public void Enter() {
// Поток хочет получить блокировку
if (Interlocked.Increment(ref m_waiters) == 1)
return; // Блокировка свободна, конкуренции нет, возвращаем управление
// Блокировка захвачена другим потоком (конкуренция),
// приходится ждать.
m_waiterLock.WaitOne(); // Значительное снижение производительности
// Когда WaitOne возвращет управление, этот поток блокируется
}
public void Leave() {
// Этот поток освобождает блокировку
if (Interlocked.Decrement(ref m_waiters) == 0)
return; // Другие потоки не заблокированы, возвращаем управление
// Другие потоки заблокированы, пробуждаем один из них
m_waiterLock.Set(); // Значительное снижение производительности
}
public void Dispose() { m_waiterLock.Dispose(); }
}
Класс
SimpleHybridLock
содержит два поля: одно типа
Int32
, управляе-
мое примитивными конструкциями пользовательского режима, и второе типа
AutoResetEvent
, являющееся примитивной конструкцией режима ядра. Чтобы
добиться более высокой производительности, при блокировании нужно пытаться
использовать поле
Int32
и по возможности не использовать поле
AutoResetEvent
.
Поле
AutoResetEvent
создается при конструировании объекта
SimpleHybridLock
и является причиной значительного снижения производительности, особенно по
сравнению с полем
Int32
. Далее в этой главе рассматривается еще одна гибридная
конструкция (
AutoResetEventSlim
), которая не создает поля
AutoResetEvent
до
возникновения конкуренции со стороны потоков, одновременно пытающихся до-
биться права на блокирование. Закрывающий поле
AutoResetEvent
метод
Dispose
также значительно снижает производительность.
Как ни заманчиво выглядит задача повышения производительности при соз-
дании и освобождении объекта
SimpleHybridLock
, лучше сосредоточиться на его
методах
Enter
и
Leave
, вызываемых за время жизни объекта бессчетное количество
раз. Давайте рассмотрим их подробно.
Первый вызвавший метод
Enter
поток заставляет метод
Interlocked.Incre-
ment
увеличить поле
m_waiters
на 1, сделав его значение равным единице. Поток
обнаруживает, что прежде потоков, ожидающих права на данное блокирование,
не было, поэтому после вызова метода
Enter
он возвращает управление. Здесь
856
Do'stlaringiz bilan baham: |