Главная страница Случайная страница Разделы сайта АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Мониторы
Оператор lock фактически является надстройкой над классом Monitor. Запись: lock(locker) {< критическая секция> } можно рассматривать как краткую форму следующей записи: Monitor.Enter(locker) try {< критическая секция> } finally { Monitor.Exit(locker)} Статический метод Enter класса Monitor закрывает критическую секцию, погруженную в try-блок, ссылочным объектом locker. Семантика такая же, как и у оператора lock. Все остальные потоки, пытающиеся войти в критическую секцию, закрытую ключом locker, будут выстраиваться в очередь, ожидая, пока секция не будет открыта. При любом завершении try-блока выполняется блок finally, снимающий блокировку. У класса Monitor есть и другие методы, позволяющие организовать блокировку. Класс Monitor предоставляет метод TryEnter, имеющий следующий синтаксис: public static bool TryEnter( Object obj, int millisecondsTimeout ) Метод представляет функцию, возвращающую значение true, если за время ожидания, заданное параметром millisecondsTimeout, произошел вход в критическую секцию. Такая форма входа в критическую секцию нам уже знакома по описанию класса ReaderWriterLockSlim. Метод TryEnter перегружен и имеет еще две формы вызова, немногим отличающимся по семантике. У класса Monitor есть еще три важных метода - Wait, Pulse, PulseAll. Эти методы вызываются внутри критической секции. Они взаимосвязаны и позволяют двум или нескольким потокам синхронизировать свою работу, посылая друг другу уведомления. Пусть, выполняя действия в критической секции, поток обнаруживает, что другой поток должен выполнить некоторую обработку закрытого ресурса. В этой ситуации поток должен приостановить свою работу, освободить временно ресурс, чтобы дать другому потоку провести необходимую обработку, а затем уведомить приостановленный поток, что он может продолжить работу. Методы Wait - Pulse позволяют реализовать описанный сценарий. Метод Wait позволяет приостановить работу потока в критической секции. Метод Pulse посылает уведомление, позволяющее приостановленному потоку продолжить выполнение. Метод PulseAll позволяет продолжить выполнение всем приостановленным потокам. Метод Wait перегружен, и мы рассмотрим только основной его вариант, имеющий следующий синтаксис: public static bool Wait(object obj); Параметр obj задает синхронизирующий объект, закрывающий критическую секцию. Обычно метод не использует возвращаемое значение и вызывается как оператор, а не как функция. Точная семантика метода такова. Метод освобождает синхронизирующий объект, поток прерывает работу и становится в специальную очередь ожидания уведомления. Когда другой метод, захвативший освобожденный объект синхронизации, выполняет метод Pulse, то первый метод из очереди ожидания переводится в очередь готовых к исполнению потоков. Когда настает черед выполняться методу, то восстанавливается его состояние, восстанавливаются все ранее сделанные блокировки и метод продолжает работать. Метод Pulse имеет следующий синтаксис: public static void Pulse(object obj); При выполнении метода уведомляется очередь ожидания потоков с синхронизирующим объектом obj. В результате поток из этой очереди переходит в состояние готовность. Когда поток, вызвавший метод Pulse, освободит блокировку, то готовый поток продолжит выполнение. Кооперация методов Wait - Pulse позволяет решать многие задачи взаимодействия потоков, которые невозможно решить другими способами.
|