
- •Пояснительная записка
- •Задание
- •Оглавление
- •1 Введение
- •2.Основная часть
- •2.1 Описание методологии мониторов
- •2.2 Синтаксис и семантика
- •2.3 Взаимное исключение
- •2.4 Условные переменные
- •2.5 Дисциплины сигнализации
- •2.6 Взаимоисключительность
- •2.7 Применение
- •3 Заключение Список используемых источников
2.5 Дисциплины сигнализации
Выполняя операцию signal, процесс работает в мониторе и, следовательно, может управлять блокировкой, неявно связанной с монитором. В результате возникает дилемма. Если операция signal запускает другой процесс, то получается, что могли бы выполняться два процесса: вызвавший операцию signal и запущенный ею. Но следующим может выполняться только один из них (даже на мультипроцессорах), поскольку лишь один процесс может иметь исключительный доступ к монитору. Таким образом, возможны два варианта:
• сигнализировать и продолжить: сигнализатор продолжает работу, а процесс, получивший сигнал, выполняется позже;
• сигнализировать и ожидать: сигнализатор ждет некоторое время, а процесс, получивший сигнал, выполняется сразу.
Дисциплина (порядок) "сигнализировать и продолжить" не прерывает обслуживания. Процесс, выполняющий операцию signal, сохраняет исключительный доступ к монитору, а запускаемый процесс начнет работу несколько позже, когда получит исключительный доступ к монитору. По существу, операция signal просто указывает запускаемому процессу на возможность выполнения, после чего он возвращается в очередь процессов, ожидающих на блокировке монитора.
Порядок "сигнализировать и ожидать" имеет свойство прерывания обслуживания. Процесс, выполняющий операцию signal, передает управление блокировкой монитора запускаемому процессу, т.е. запускаемый процесс прерывает работу процесса-сигнализатора. В этом случае сигнализатор переходит в очередь процессов, ожидающих на блокировке монитора. (Возможен вариант, когда сигнализатор помещается в начало очереди ожидающих процессов; это называется "сигнализировать и срочно (urgent) ожидать".)
Рисунок 1 - Диаграмма состояний для синхронизации в мониторах
Диаграмма состояний на рисунке 1 иллюстрирует работу синхронизации в мониторах. Вызывая процедуру монитора, процесс помещается во входную очередь, если в мониторе выполняется еще один процесс; в противном случае вызвавший операцию процесс немедленно начинает выполнение в мониторе. Когда монитор освобождается (после возврата из процедуры или выполнения операции wait), один процесс из входной очереди может перейти к работе в мониторе. Выполняя операцию wait(cv), процесс переходит от работы в мониторе в очередь, связанную с условной переменной. Если процесс выполняет операцию signal(cv), то при порядке "сигнализировать и продолжить" (Signal and Continue - SC) процесс из начала очереди условной переменной переходит во входную. При порядке "сигнализировать и ожидать" (Signal and Wait - SW) процесс, выполняемый в мониторе, переходит во входную очередь, а процесс из начала очереди условной переменной переходит к выполнению в мониторе.
2.6 Взаимоисключительность
Монитор состоит из:
набора процедур, взаимодействующих с общим ресурсом
мьютекса
переменных, связанных с этим ресурсом
инварианта, который определяет условия, позволяющие избежать состояние гонки
Процедура монитора захватывает мьютекс перед началом работы и держит его или до выхода из процедуры, или до момента ожидания условия (см. ниже). Если каждая процедура гарантирует, что перед освобождением мьютекса инвариант истинен, то никакая задача не может получить ресурс в состоянии, ведущем к гонке.
Простой пример. Рассмотрим монитор, выполняющий транзакции банковского счёта.
monitor account {
int balance := 0
function withdraw(int amount) {
if amount < 0 then error "Счёт не может быть отрицательным"
else if balance < amount then error "Недостаток средств"
else balance := balance - amount
}
function deposit(int amount) {
if amount < 0 then error "Счёт не может быть отрицательным"
else balance := balance + amount
}
}
Инвариант здесь просто утверждает, что баланс должен отразить все прошедшие операции до того, как начнётся новая операция. Обычно это не выражено в коде, но подразумевается и может быть упомянуто в комментариях. Однако, есть языки программирования, такие как Эйфель или D, которые могут проверять инварианты. Блокировка добавлена компилятором. Это делает мониторы безопаснее и удобнее, чем другие подходы, требующие от программиста вручную добавлять операции блокировки-разблокировки, — поскольку программист может забыть добавить их.