Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ответы ОСиСП.doc
Скачиваний:
68
Добавлен:
11.05.2015
Размер:
1.78 Mб
Скачать

Использование класса Monitor для управления блоком синхронизации

Познакомившись с инфраструктурой блоков синхронизации, перейдем к рассмотрению установки и отмены блокировки объекта. Чтобы заблокировать/разблокировать блок синхронизации, вызывают статические методы, определенные в классе System.Threading.Monitor. Вот метод, который можно вызвать, чтобы заблокировать блок синхронизации объекта:

static void Enter(Object obj);

При вызове этот метод сначала проверяет, отрицателен ли указанный индекс блока синхронизации; если да, метод находит свободный блок синхронизации и записывает его индекс в индекс блока синхронизации объекта. Кстати, в CLR механизм поиска свободного блока синхронизации и связывания его с объектом обеспечивает безопасность потоков. После связывания блока с объектом метод MonitorEnter проверяет указанный блок синхронизации — не занят ли он другим потоком. Если блок свободен, вызывающий поток становится владельцем блока. Если же этим блоком владеет другой поток, вызывающий поток приостанавливается, пока владеющий этим блоком поток не освободит его.

Если нужно создать более надежный код, вместо MonitorEnter можно вызвать метод Monitor.TryEnter (у него три перегруженных версии):

static Boolean TryEnter(Object obj);

static Boolean TryEnter(object obj, Int32 millisecondsTimeout);

static Boolean TryEnter(Object obj, TimeSpan timeout);

Первая версия просто проверяет, может ли вызывающий поток занять блок синхронизации и при положительном результате возвращает значение true. Две другие версии позволяют указать время тайм-аута — сколько вызывающий поток будет ожидать освобождения блока. Все методы возвращают false, если занять блок синхронизации не удалось.

После того как поток стал владельцем блока синхронизации, код получает доступ к любым данным блока синхронизации, для защиты которых он используется. По завершении работы с блоком поток должен освободить его вызовом метода Monitor.Exit:

static void Exit(Object obj);

Если поток, вызывающий метод Monitor.Exit, не владеет указанным блоком синхронизации, генерируется исключение SynchronizationLockException. Заметьте также, что поток может владеть блоком синхронизации рекурсивно, но при этом каждому успешному вызову метода Monitor.Enter или Monitor.TryEnter должен соответствовать вызов метода Monitor.Exit — только после этого блок может считаться свободным.

Способ синхронизации, предлагаемый Microsoft

Познакомимся с примерами кода, демонстрирующими, как Microsoft предлагает разработчикам использовать класс Monitor и блоки синхронизации:

internal sealed class Transaction

{

// Поле, показывающее время последней выполненной транзакции,

private DateTime timeOfLastTransaction;

public void PerformTransaction()

{

Monitor.Enter(this);

// Выполнение транзакции...

// Запись времени последней транзакции.

timeOfLastTransaction = DateTime.Now;

Monitor.Exit(this); // Отмена блокировки объекта.

}

// Неизменяемое свойство, возвращающее время последней транзакции.

public DateTime LastTransaction

{

get

{

Monitor.Enter(this); // Блокировка объекта.

// Сохранение времени выполнения последней транзакции

// во временной переменной.

DateTime dt = timeOfLastTransaction;

Monitor.Exit(this);

// Отмена блокировки объекта,

return dt; // Возвращение сохраненных даты и времени.

}

}

}

В этом примере показано, как использовать методы Enter и Exit метода Monitor для блокировки и разблокировки блока синхронизации объекта.

Реализация свойства требует вызовов методов Enter и Exit и наличия временной переменной dt. Это нужно для исключения возможности повреждения возвращаемого значения — это возможно, если в момент вызова потоком метода PerformTransaction к свойству обращается другой поток.

Приведенный выше код демонстрирует, как специалисты Microsoft первоначально предлагали использовать блоки синхронизации объекта. Однако в процессе работы этого кода возможно возникновение серьезных проблем.