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;