goto L2
end;
parend
end
Главный недостаток такого взаимодействия состоит в том, что, невзирая на различие скоростей параллельно идущих процессов 1 и 2, вход каждого процесса в свою критическую секцию оказывается строго поочередным.
Исключить очередность входа процессов в критическую секцию можно введением двух флажков ф1 и ф2, принимающих значения: 0 или 1. Значение ф1=0 означает нахождение процесса 1 внутри критического интервала, а ф1=1 – вне. Аналогичным образом ф2=0 определяет нахождение процесса 2 внутри, а ф2=1 – вне критического интервала.
Решение этой задачи представлено схемой алгоритма except-1 на рисунке 2.18б, а псевдокод реализации этого варианта имеет следующий вид:
begin integer ф1, ф2; ф1:= 1; ф2:= 1;
parbegin
процесс 1: begin L1: if ф2 = 0 then goto L1;
ф1:= 0;
критический интервал 1;
ф1:= 1;
остаток цикла 1; goto L1
end;
процесс 2: begin L2: if ф1 = 0 then goto L2;
ф2:= 0;
критический интервал 2;
ф2:= 1;
остаток цикла 2; goto L2
end;
parend;
end
Первоначальные присваивания флажкам ф1 и ф2 значений, равных 1, связано с тем, что процессы начинаются вне своих критических интервалов. При входе первого процесса внутрь своего критического интервала будет сохраняться условие ф1=0 вплоть до момента выхода из него. Если в течение критического интервала процесса 1 к своему критическому интервалу подойдет процесс 2 и выполнит проверку занятости, то он будет выполнять ее до момента выхода процесса 1 из его критической секции. Строгая очередность входа процессов в свои критические секции в этом решении исключена, так как при выходе из критических интервалов процессы всегда оставляют для себя условия, разрешающие вход в свой критический интервал. Кроме того, реализуется взаимное исключение одновременного входа в критические интервалы.
Однако из-за различия скоростей процессов или вынужденных задержек возможна следующая ситуация. Пусть сначала процесс 1 обнаруживает, что ф2=1, а процесс 2 немедленно вслед за этим проверяет значение ф1 и тоже находит, что ф1=1. Каждый из процессов, удостоверившись, что другой процесс не находится в критическом интервале, входит в свой собственный критический интервал – и данные испорчены!
Рисунок 2.18.
Наверное, проверку допустимости входа в свою критическую секцию и установку своего флажка в ноль необходимо поменять местами? Этот вариант приведен на рисунке 2.19 со следующим фрагментом псевдокода:
begin
integer ф1, ф2;
ф1:= 1; ф2:= 1;
parbegin
пр_1: begin
A1: ф1:= 0;
B1: if ф2 = 0 then goto B1;
критическая секция 1;
ф1:= 1;
остаток цикла 1; goto A1
end;
пр_2: begin
A2: ф2:= 0;
B2: if ф1 = 0 then goto B2;
критическая секция 2;
ф2:= 1;
остаток цикла 2; goto A2
end;
parend;
end
Рисунок 2.19.
Однако и здесь обнаруживается ситуация, когда произойдет взаимная блокировка. Например, если в процессе 1 после присваивания ф1:=1, но еще до проверки флажка ф2, процесс 2 выполнит присваивание ф2:=0, то это будет означать, что оба процесса достигли своих меток В1, В2. Так как при этом флажки одновременно имеют значения, запрещающие вход в свои критические интервалы, то налицо тупиковая ситуация.
Очевидно, что длительного ожидания допуска в критическую секцию с неизменяемым состоянием собственного флажка оставлять ни в процессе 1, ни в процессе 2 нельзя. Необходимо, сделать так, чтобы синхронность входа процессов, возникающая из-за равенства скоростей процессов, нарушалась самими процессами в тот момент, когда закончилась одновременная проверка чужих флажков. Удачное решение, найденное голландским математиком Деккером, представлено на рисунке 2.20.
Рисунок 2.20.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.