
Лекция 07. Пара «производитель—потребитель»
1.Реализация взаимодействия в паре «производитель—потребитель»
Когда в последовательной программе одна процедура вызывает другую и передает ей данные, обе эти процедуры являются частями единого процесса — они не выполняются параллельно. Если, однако, один процесс передает данные другому процессу, возникают определенные проблемы. Подобная передача может служить примером взаимодействия, или обмена информацией между процессами.
Рассмотрим следующую пару (отношение) «производитель— потребитель». Предположим, что один процесс, источник, или производитель, генерирует информацию, которую другой процесс, получатель, или потребитель, использует. Предположим, что они взаимодействуют при помощи одной разделяемой целой переменной с именем «буферчисла». Процесс-производитель производит некоторые вычисления, а затем заносит результат в «буферчисла»; процесс-потребитель читает «буферчисла» и печатает результат.
Возможно, что эти процессы, производитель и потребитель, работают в достаточно близком темпе либо резко различаются по скоростям. Если каждый раз, когда процесс-производитель помещает свой результат в «буферчисла», процесс-потребитель будет немедленно считывать и печатать его, то на печать будет верно выдаваться та последовательность чисел, которую формировал процесс-производитель.
Предположим теперь, что скорости обоих процессов резко различны. Если процесс-потребитель работает быстрее, чем процесс-производитель, он может прочитать и напечатать одно и то же число дважды (или в общем случае много раз), прежде чем процесс-производитель выдаст следующее число. Если же процесс-производитель работает быстрее, чем потребитель, он может записать новый результат на место предыдущего до того, как процесс-потребитель успеет прочитать и напечатать этот предшествующий результат; процесс-производитель, работающий с очень высокой скоростью, фактически может по несколько раз перезаписывать результат, так что будет потеряно много результатов.
Очевидно, что здесь мы хотели бы обеспечить такое взаимодействие процесса-производителя и процесса-потребителя, при котором данные, заносимые в «буферчисла», никогда не терялись бы и не дублировались. Создание подобного режима взаимодействия является примером синхронизации процессов.
На рис. 1 показана параллельная программа, в которой для реализации взаимодействия в паре «производитель — потребитель» применяются операции над семафорами.
В этой программе мы ввели два семафора: «исключительныйдоступ» используется для обеспечения доступа к разделяемой переменной в режиме взаимоисключения, а «числозанесено» - для обеспечения синхронизации процессов.
program парапроизводительпотребитель;
var исключительныйдоступ: семафор;
числозанесено: семафор;
буферчисла: целое;
procedure процесспроизводитель;
var следующийрезультат: целое;
begin
while истина do begin
вычислениеследующегорезультата;
Р(исключительныйдоступ);
буферчисла : = следующийрезультат;
V(исключительныйдоступ);
V(числозанесено)
end
end;
procedure процесс потребитель;
var следующийрезультат: целое;
begin
while истина do begin
Р(числозанесено);
Р(исключительныйдоступ);
следующийрезультат : = буферчисла;
V( исключительныйдоступ);
записать (следующий результат)
end
end;
begin инициализациясемафора(исключительныйдоступ,1);
инициализациясемафора(числозанесено,0);
parbegin
процесспроизводитель;
процесспотребитель parend
end;
Рис. 1.Реализация взаимодействия в паре «производитель—потребитель» при помощи
семафоров.
2. Считающие семафоры
Считающие семафоры особенно полезны в случае, если некоторый ресурс выделяется из пула идентичных ресурсов. При инициализации подобного семафора в его счетчике указывается количественный показатель объема ресурсов пула. Каждая операция Р вызывает уменьшение значения счетчика семафора на 1, показывая, что некоторому процессу для использования выделен еще один ресурс из пула. Каждая операция V вызывает увеличение значения счетчика семафора на 1, показывая, что процесс возвратил в пул ресурс и этот ресурс может быть выделен теперь другому процессу. Если делается попытка выполнить операцию Р, когда в счетчике семафора уже нуль, то соответствующему процессу придется ждать момента, пока в пул не будет возвращен освободившийся ресурс, т. е. пока не будет выполнена операция V.