Задача «поставщик – потребитель»
Решение задачи «поставщик – потребитель» является характерным примером использования семафорных операций. Содержательная постановка этой задачи уже была нами описана в первом разделе данной главы. Разделяемыми переменными здесь являются счётчики свободных и занятых буферов, которые должны быть защищены со стороны обоих процессов, то есть действия по посылке и получению сообщений должны быть синхронизированы.
Использование семафоров для решения данной задачи приведено в листинге 6.11.
Листинг 6.11. Решение задачи «поставщик – потребитель»
var S_свободно, S_заполнено, S_взаимоискл : semaphore;
begin
initSem(S_свободно,N);
initSem(S_заполнено,0);
initSem(S_взаимоискл,1);
parbegin
ПОСТАВЩИК: while true do
begin
…{ приготовить сообщение }
Р(S_свободно);
Р(S_взаимоискл);
…{послать сообщение }
V(S_заполнено);
V(S_взаимоискл);
end
and
ПОТРЕБИТЕЛЬ: while true do
begin
Р(S_заполнено);
Р(S_взаимоискл);
…{ получить сообщение }
V(S_свободно);
V(S_взаимоискл);
…{ обработать сообщение }
end
parend
end.
Здесь переменные S_свободно, S_заполнено являются числовыми семафорами, S_взаимоискл – двоичный семафор. S_свободно имеет начальное значение, равное N, где N – количество буферов, с помощью которых процессы связываются. Предполагается, что в начальный момент количество свободных буферов равно N; соответственно, количество занятых равно нулю. Двоичный семафор S_взаимоискл гарантирует, что в каждый момент только один процесс сможет работать с критическим ресурсом, выполняя свой критический интервал. Семафоры S_свободно и S_заполнено используются как счётчики свободных и заполненных буферов. Действительно, перед посылкой сообщения «поставщик» уменьшает значение S_свободно на единицу в результате выполнения Р(S_свободно), а после посылки сообщения увеличивает значение S_заполнено на единицу в результате выполнения V(S_заполнено). Аналогично, перед получением сообщения «потребитель» уменьшает значение S_заполнено в результате выполнения Р(S_заполнено), а после получения сообщения увеличивает значение S_свободно в результате выполнения V(S_свободно). Семафоры S_заполнено, S_свободно могут также использоваться для блокировки соответствующих процессов. Если пул буферов оказался пустым и к нему первым обратится процесс «потребитель», он заблокируется на семафоре S_заполнено в результате выполнения Р(S_заполнено). Если пул буферов заполнен и к нему в этот момент обратится процесс «поставщик», то он будет заблокирован на семафоре S_свободно в результате выполнения Р(S_свободно).
В решении задачи о «поставщике» и «потребителе» общие семафоры применены для учёта свободных и заполненных буферов. Их можно также применить и для распределения иных ресурсов.
Дата добавления: 2022-02-05; просмотров: 407;