- •4.10 Аппаратная реализация взаимоисключения:
- •Testandset (a, b)
- •4.11 Семафоры
- •4.12 Синхронизация процессов при помощи семафоров
- •4.13 Пара "производитель-потребитель"
- •4.14 Считающие семафоры
- •5.2 Мониторы
- •5.3 Простое распределение ресурсов при помощи мониторов
- •5.4 Пример монитора: кольцевой буфер
- •5.5 Пример монитора: читатели и писатели
4.14 Считающие семафоры
Считающие семафоры особенно полезны в случае, если некоторый ресурс выделяется из пула идентичных ресурсов. При инициализации подобного семафора в его счетчике указывается количественный показатель объема ресурсов пула. Каждая операция Р вызывает уменьшение значения счетчика семафора на 1, показывая, что некоторому процессу для использования выделен еще один ресурс уз пула. Каждая операция V вызывает увеличение значения счетчика семафора на 1, показывая, что процесс возвратил в пул ресурс и этот ресурс может быть выделен теперь другому процессу.
Если делается попытка выполнить операцию Р, когда в счетчике семафора уже нуль, то соответствующему процессу придется ждать момента, пока в пул не будет возвращен освободившийся ресурс, т. е. пока не будет выполнена операция V.
5.2 Мониторы
Монитор – это механизм организации параллелизма, который содержит :
как данные,
так и процедуры,
необходимые для реализации динамического распределения конкретного общего ресурса или группы общих ресурсов.
Чтобы обеспечить выделение нужного ему ресурса, процесс должен обратиться к конкретной процедуре монитора.
Необходимость входа в монитор в различные моменты времени может возникать у многих процессов. Однако вход в монитор находится под жестким контролем – здесь осуществляется взаимоисключение процессов, так что в каждый момент времени только одному процессу разрешается войти в монитор. Процессам, которые хотят войти в монитор, когда он уже занят, приходится ждать, причем режимом ожидания автоматически управляет сам монитор.
Поскольку механизм монитора гарантирует взаимоисключение процессов, исключаются серьезные проблемы, связанные с параллельным режимом работы.
Внутренние данные монитора могут быть
либо глобальными (относящимися ко всем процедурам монитора),
либо локальными (относящимися только к одной конкретной процедуре).
Ко всем этим данным можно обращаться только изнутри монитора;
процессы, находящиеся вне монитора, просто не могут получить доступа к данным монитора.
Принимая такое структурное решение, значительно упрощающее разработку программных систем повышенной надежности, говорят, что информация спрятана.
Если процесс обращается к некоторой процедуре монитора и обнаруживается, что соответствующий ресурс уже занят, эта процедура монитора выдает команду ожидания WAIT. Процесс мог бы оставаться внутри монитора, однако это привело бы к нарушению принципа взаимоисключения, если в монитор затем вошел бы другой процесс. Поэтому процесс, переводящийся в режим ожидания, должен вне монитора ждать того момента, когда необходимый ему ресурс освободится.
Со временем процесс, который занимал данный ресурс, обратится к монитору, чтобы возвратить ресурс системе. Соответствующая процедура монитора при этом может просто принять уведомление о возвращении ресурса, а затем ждать, пока не поступит запрос от другого процесса, которому потребуется этот ресурс. Однако может оказаться, что уже имеются процессы, ожидающие освобождения данного ресурса. В этом случае монитор выполняет примитив оповещения (сигнализации) SIGNAL, чтобы один из ожидающих процессов мог занять данный ресурс и покинуть монитор. Если процесс сигнализирует о возвращении (иногда называемом освобождением) ресурса и в это время нет процессов, ожидающих данного ресурса, то подобное оповещение не вызывает никаких других последствий, кроме того, что монитор естественно вновь вносит ресурс в список свободных. Очевидно, что процесс, ожидающий освобождения некоторого ресурса, должен находиться вне монитора, чтобы другой процесс имел возможность войти в монитор и возвратить ему этот ресурс.
Чтобы гарантировать, что процесс, находящийся в ожидании некоторого ресурса, со временем действительно получит этот ресурс, считается, что ожидающий процесс имеет более высокий приоритет, чем новый процесс, пытающийся войти в монитор. В противном случае новый процесс мог бы перехватить ожидаемый ресурс до того, как ожидающий процесс вновь войдет в монитор. Если допустить многократное повторение подобной нежелательной ситуации, то ожидающий процесс мог бы откладываться бесконечно.
Фактически, у процессов может возникнуть желание (и необходимость) находиться в режиме ожидания вне монитора по многим различным причинам. Поэтому было введено понятие переменной-условия.
Для каждой отдельно взятой причины, по которой процесс может быть переведен в состояние ожидания, назначается свое условие. В связи с этим команды ожидания и сигнализации модифицируются – в них включаются имена условий:
wait(имяycлoвия)
signal(имяусловия)
Переменные-условия совершенно не похожи на "обычные" переменные, с которыми мы привыкли иметь дело.
Когда определяется такая переменная:
заводится очередь.
Процесс, выдавший команду ожидания, включается в эту очередь,
а процесс, выдавший команду сигнализации, тем самым позволяет ожидающему процессу выйти из очереди и войти в монитор.