W systemie działa N grup procesów. Każdy proces cyklicznie wykonuje procedure własne sprawy, a następnie procedurę OBLICZ, którą w tym samym czasie mogą wykonywać tylko procesy należące do tej samej grupy. Pierwszy proces z grupy może rozpocząć wykonywanie procedury OBLICZ tylko wówczas, gdy nikt inny jej nie wykonuje. Po zakończeniu wykonywania procedury OBLICZ procesy czekają aż wszystkie wykonujące ją procesy zakończą jej wykonywanie. Po zakończeniu procedury przez ostatni z wykonujących ją procesów działanie powinny rozpocząć oczekujące procesy z kolejnej grupy. Zwróć uwagę, że mowa tu jest o wszystkich wykonywanych procesach danej grupy, a nie o wszystkich procesach danej grupy. Oznacza to, że nie wszystkie procesy z danej grupy muszą wykonać OBLICZ, aby rozpoczęła działanie następna grupa. Uzupełnij treść procesu P używając semaforów.
procedure rozpoczecie_obliczen(gr: 1..N) begin ... end; procedure zakonczenie_obliczen(gr: 1..N) begin ... end; process Proces(gr: 1..N) begin while (true) do begin WLASNE_SPRAWY(); rozpoczecie_obliczen(); OBLICZ(); zakonczenie_obliczen(); end; end;
Rozwiązanie:
var
ochrona: binary semaphore := 1;
pierwsi: binary semaphore := 0;
oczekiwanie_na_zakonczenie: binary semaphore := 0;
grupa_aktywna: integer := 0;
reszta_grupy_czeka: array [1..N] of binary semaphore := {N times 0};
liczba_czekajacych: array [1..N] of integer := {N times 0};
liczba_aktywnych: integer := 0;
liczba_aktywnych_zakonczonych: integer := 0;
ile_grup_czeka: integer := 0;
procedure rozpoczecie_obliczen(gr: 1..N)
begin
P(ochrona);
if (grupa_aktywna=0) then
begin
grupa_aktywna:=gr;
end;
if (grupa_aktywna<>gr) then
begin
liczba_czekajacych[gr]++;
if (liczba_czekajacych[gr]>1) then
V(ochrona);
P(reszta_grupy_czeka[gr]);
else
begin
ile_grup_czeka++;
V(ochrona);
P(pierwsi);
ile_grup_czeka--;
grupa_aktywna := gr;
end;
liczba_czekajacych[gr]--;
liczba_aktywnych++;
if (liczba_czekajacych[gr]>0) then
V(reszta_grupy_czeka[gr]);
else
V(ochrona);
end;
else
begin
liczba_aktywnych++;
V(ochrona);
end;
end;
procedure zakonczenie_obliczen(gr: 1..N)
begin
P(ochrona);
liczba_aktywnych_zakonczonych++;
if (liczba_aktywnych<>liczba_aktywnych_zakonczonych) then
begin
V(ochrona);
P(oczekiwanie_na_zakonczenie);
end;
liczba_aktywnych--;
if (liczba_aktywnych<>0)
V(oczekiwanie_na_zakonczenie);
else
begin
grupa_aktywna=0;
liczba_aktywnych_zakonczonych=0;
if (ile_grup_czeka>0)
V(pierwsi);
else
V(ochrona);
end;
end;
process Proces(gr: 1..N)
begin
while (true) do
begin
WLASNE_SPRAWY();
rozpoczecie_obliczen();
OBLICZ();
zakonczenie_obliczen();
end;
end;