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;