W systemie 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;
var
partner: 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 w danej chwili może 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.
Rozwiązanie:
monitor SERWER;
czeka_pierwszy: condition;
czeka_grupa: array [1..N] of condition;
liczba_czekajacych_w_grupie: array [1..N] of integer;
czeka_na_zasob: array [1..K] of condition;
zasob_zajety: array [1..K] of 0..1 := {K TIMES 0};
grupa_korzystajaca: integer := -1;
ilu_korzysta: integer := 0;
export procedure chce_korzystac(grupa: 1..N, k: 1..K)
begin
if (grupa_korzystajaca == -1) then
grupa_korzystajaca := grupa;
if (not empty(czeka_pierwszy) || grupa_korzystajaca <> grupa) then
begin
++liczba_czkejacych_w_grupie[grupa];
if (liczba_czekajacych_w_grupie[grupa] == 1) then
begin
wait(czeka_pierwszy);
grupa_korzystajaca := grupa;
end;
else
begin
wait(czeka_grupa[grupa]);
end;
--liczba_czkejacych_w_grupie[grupa];
end;
ilu_korzysta++;
signal(czeka_grupa[grupa]);
if (zasob_zajety[k])
wait(czeka_na_zasob[k]);
zasob_zajety[k] := 1;
end;
export procedure skonczylem(k: 1..K)
begin
zasob_zajety[k] := 0;
signal(czeka_na_zasob[k]);
ilu_korzysta--;
if (ilu_korzysta == 0) then
begin
grupa_korzystajaca := -1;
signal(czeka_pierwszy);
end;
end;