W systemiie N>1 grup procesów (liczność grup nie jest znana) korzysta z K>1 zasobów ponumerowanych od 1 do K. Każdy proces działa według schematu:
process P(grupa: 1..N); var k: integer; begin while true do begin wlasne_sprawy; SERWER.chce_korzystac(grupa, k); korzystam(k); SERWER.skonczylem(k); end; end;
Zasady korzystania z zasobów są następujące:
Procesy różnych grup nie mogą korzystać jednocześnie z zasobów.
Z danego zasobu może w danej chwili korzystać tylko jeden proces.
Należy zadbać o efektywność rozwiązania - kiedy z zasobów zaczyna korzystać kolejna grupa, należy wykorzystać tyle zasobów, ile to możliwe.
Napisz monitor SERWER zarządzający dostępem do zasobów w taki sposób, aby powyższe warunki były spełnione i żaden proces nie został zagłodzony.
Rozwiązanie:
monitor SERWER;
type
status_zasobu_t = (wolny, zajety)
var
czeka_grupa: array [1..N] of condition;
czeka_lider: condition;
czy_czeka_lider: array [1..N] of boolean := N times false;
czeka_na_zasob: array[1..K] of condition;
status_zasobu: array[1..K] of status_zasobu_t := N times wolny;
aktualna_grupa: integer;
liczba_procesow_zatwierdzonych: integer := 0;
export procedure chce_korzystac(grupa: 1..N, zasob: 1..K)
begin
if (liczba_procesow_zatwierdzonych=0) then
aktualna_grupa := grupa;
else if (grupa<>aktualna_grupa or not empty(czeka_lider)) then
if (not czy_czeka_lider[grupa]) then
begin
czy_czeka_lider[grupa] := true;
wait(czeka_lider);
aktualna_grupa := grupa;
czy_czeka_lider[grupa] := false;
end;
else
wait(czeka_grupa[grupa]);
liczba_procesow_zatwierdzonych++;
signal(czeka_grupa[aktualna_grupa]); {:aktualna_grupa=grupa:}
if (status_zasobu[zasob]=zajety)
wait(czeka_na_zasob[zasob])
status_zasobu[zasob]:=zajety;
end;
export procedure skonczylem(zasob: 1..K)
begin
status_zasobu[zasob]:=wolny;
signal(czeka_na_zasob[zasob]);
liczba_procesow_zatwierdzonych--;
if (liczba_procesow_zatwierdzonych=0) then
signal(czeka_lider);
end;