The design of the UNIX Operating System 30 страница
}
Легко убедиться, что это действительно корректное решение поставленной задачи. Попутно заметим, что семафоры использовались здесь для достижения двух целей: организации взаимоисключения на критиче-ском участке и взаимосинхронизации скорости работы процессов.
Мониторы
Хотя решение задачи producer-consumer с помощью семафоров выглядит достаточно изящно, програм-мирование с их использованием требует повышенной осторожности и внимания, чем отчасти напоминает программирование на языке Ассемблера. Допустим, что в рассмотренном примере мы случайно поменя-ли местами операции P, сначала выполнив операцию для семафора mutex, а уже затем для семафоров full и empty. Допустим теперь, что потребитель, войдя в свой критический участок (mutex сброшен), обнару-живает, что буфер пуст. Он блокируется и начинает ждать появления сообщений. Но производитель не
|
|
Основы операционных систем | 60 |
|
|
может войти в критический участок для передачи информации, так как тот заблокирован потребителем. Получаем тупиковую ситуацию.
В сложных программах произвести анализ правильности использования семафоров с карандашом в руках становится очень непросто. В то же время обычные способы отладки программ зачастую не дают резуль-тата, поскольку возникновение ошибок зависит от interleaving атомарных операций, и ошибки могут быть трудновоспроизводимы. Для того чтобы облегчить работу программистов, в 1974 году Хором (Hoare) был предложен механизм еще более высокого уровня, чем семафоры , получивший название мо-ниторов. Мы с вами рассмотрим конструкцию, несколько отличающуюся от оригинальной.
|
|
|
|
Мониторы представляют собой тип данных, который может быть с успехом внедрен в объектно-ориентированные языки программирования. Монитор обладает собственными переменными, опреде-ляющими его состояние. Значения этих переменных извне могут быть изменены только с помощью вы-зова функций-методов , принадлежащих монитору. В свою очередь, эти функции-методы могут исполь-зовать в работе только данные, находящиеся внутри монитора, и свои параметры. На абстрактном уровне можно описать структуру монитора следующим образом:
monitor monitor_name {
описание внутренних переменных ;
void m1(...){...
}
void m2(...){...
}
...
void mn(...){...
}
{
блок инициализации внутренних переменных;
}
}
Здесь функции m1,..., mn представляют собой функции-методы монитора, а блок инициализации внутрен-них переменных содержит операции, которые выполняются один и только один раз: при создании мони-тора или при самом первом вызове какой-либо функции-метода до ее исполнения.
Важной особенностью мониторов является то, что в любой момент времени только один процесс может быть активен, т. е. находиться в состоянии готовность или исполнение, внутри данного монитора. По-скольку мониторы представляют собой особые конструкции языка программирования, компилятор мо-жет отличить вызов функции, принадлежащей монитору, от вызовов других функций и обработать его специальным образом, добавив к нему пролог и эпилог, реализующий взаимоисключение. Так как обя-занность конструирования механизма взаимоисключений возложена на компилятор, а не на программи-ста, работа программиста при использовании мониторов существенно упрощается, а вероятность возник-новения ошибок становится меньше.
Однако одних только взаимоисключений недостаточно для того, чтобы в полном объеме реализовать ре-шение задач, возникающих при взаимодействии процессов. Нам нужны еще и средства организации оче-редности процессов , подобно семафорам full и empty в предыдущем примере. Для этого в мониторах бы-ло введено понятие условных переменных (condition variables)1), над которыми можно совершать две операции wait и signal, отчасти похожие на операции P и V над семафорами.
Дата добавления: 2021-01-21; просмотров: 95; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!