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