- •4.10 Аппаратная реализация взаимоисключения:
- •Testandset (a, b)
- •4.11 Семафоры
- •4.12 Синхронизация процессов при помощи семафоров
- •4.13 Пара "производитель-потребитель"
- •4.14 Считающие семафоры
- •5.2 Мониторы
- •5.3 Простое распределение ресурсов при помощи мониторов
- •5.4 Пример монитора: кольцевой буфер
- •5.5 Пример монитора: читатели и писатели
4.11 Семафоры
Все описанные выше ключевые понятия, относящиеся к взаимоисключению, Дейкстра суммировал в своей концепции семафоров (Di65).
Семафор - это защищенная переменная, значение которой можно опрашивать и менять только при помощи специальных операций Р и V и операции инициализации, которую называют "инициализациясемафора".
Виды семафоров: Двоичные и Считающие.
Двоичные семафоры могут принимать только значения 0 и 1. Считающие семафоры (семафоры со счетчиками) могут принимать неотрицательные целые значения.
Операция Р над семафором записывается как P(S) и выполняется следующим образом:
если S > О
то S:= S – 1
иначе (ожидать на S)
Операция V над семафором S записывается как V(S) и выполняется следующим образом:
если (один или более процессов ожидают на S)
то (разрешить одному из этих процессов продолжить работу)
иначе S := S + 1
Мы будем предполагать, что очередь процессов, ожидающих на S, обслуживается в соответствии с дисциплиной "первый пришедший обслуживается первым" (FIFO).
Подобно операции проверки и установки testandset, операции Р и V являются неделимыми.
Участки взаимоисключения по семафору S в процессах обрамляются операциями P(S) и V(S).
Если одновременно несколько процессов попытаются выполнить операцию P(S), это будет разрешено только одному из них, а остальным придется ждать.
Семафоры и операции над ними могут быть реализованы как программно, так и аппаратно. Как правило, они реализуются в ядре операционной системы, где осуществляется управление сменой состояния процессов.
На рис. 4.9 приводится пример того, каким образом можно обеспечить взаимоисключение при помощи семафоров.
Здесь примитив Р (активный) – эквивалент для "входвзаимоисключения",
примитив V (активный) – для "выходвзаимоисключения".
program примерсемафораодин;
var активный: семафор;
procedure процессодин;
begin
while истина do
begin
предшествующиеоператорыодин;
Р(активный);
критическийучастокодин;
V (активный);
прочиеоператорыодин
end
end;
procedure процессдва;
begin
while истина do
begin
предшествующиеоператорндва;
Р(активный);
критическийучастокдва;
V (активный);
прочиеоператорыдва
end
end;
begin
инициализациясемафора(активный,1),
p
Рис.
4.9 Обеспечение
взаимоисключения при помощи семафора
и примитивов Р и V.
процессодин;
процессдва
parend
ends
4.12 Синхронизация процессов при помощи семафоров
Когда процесс выдает запрос ввода-вывода, он блокирует себя в ожидании завершения соответствующей операции ввода-вывода. Заблокированный процесс должен быть активизирован каким-либо другим процессом. Подобное взаимодействие может служить примером функций, относящихся к протоколу блокирования/возобновления.
Рассмотрим более общий случай, когда одному процессу необходимо, например, чтобы он получал уведомление о наступлении некоторого события. Предположим, что какой-либо другой процесс может обнаружить, что данное событие произошло. Программа рис. 4.10 показывает, каким образом при помощи семафора можно реализовать простой механизм синхронизации (блокирования/возобновления) для двух процессов.
program блокированиевозобновления;
var событие: семафор;
procedure процессодин;
begin
предшествующиеоператорыодин;
Р(событие);
прочиеоператорыодин
end;
procedure процессдва;
begin
предшествующиеоператорыдва;
V(событие);
прочиеоператорыдва
end;
begin
инициализадйясемафора (событие, 0);
p
Рис.
4.10 Синхронизация
блокирования/возобновление процессов
при помощи семафоров.
процессодин;
процессдва
parend
end;
Здесь "процессодин" выполняет некоторые "предшествующие операторыодин", а затем операцию Р (событие). Ранее при инициализации семафор был установлен в нуль, так что "процессодин" будет ждать. Со временем "процессдва" выполнит операцию V (событие), сигнализируя о том, что данное событие произошло. Тем самым, "процессодин" получает возможность продолжить свое выполнение.
Отметим, что подобный механизм будет выполнять свои функции даже в том случае, если "процессдва" обнаружит наступление события и просигнализирует об этом еще до того, как "процессодин", выполнит операцию Р (событие); при этом семафор переключится из 0 в 1, так что операция Р (событие) просто произведет обратное переключение, из 1 в 0, и "процессодин" продолжит свое выполнение без ожидания.