W systemie dostępne są dwa zasoby: A i B. Z zasobu A może korzystać jednocześnie X>0 procesów z zasobu B może korzystać jednocześnie Y>0 procesów. Wyróżniamy trzy typy procesów Klient:
procesy korzystające z zasobu A
procesy korzystające z zasobu B
procesy korzystające z zasobu A lub B
Napisz proces Serwer, który przydziela te zasoby.
W sposób bardziej rzeczywisty ten problem można przedstawić tak: Na komputerach A i B działa wiele procesów. Każdy komputer ma dysk twardy. Każdy proces ma preferencje: może chcieć zapisać dane na własnym dysku (proces jest typu KlientA lub KlientB), a może nie mieć takich preferencji (proces jest typu KlientAlubB). Dodatkowo z dysku komputera A może korzystać jednocześnie X procesów a z dysku komputera B może korzystać jednocześnie Y procesów.
Rozpatrzmy najpierw problem przydzielania tylko zasobu A procesom KlientA i KlientAlubB.
Przydzielanie zasobu A tylko procesom KlientA.
Process Serwer;
var
dostepnych_a: integer := X;
czeka_na_a: integer := 0;
czeka_na_alubb: integer := 0;
op: OperacjaTyp;
Procedure sprawdz_a()
begin
if (dostepnych_a>0 and czeka_na_a>0) then
begin
dostepnych_a := dostepncyh_a-1;
SendMsg(zasob_a, PozwolenieA);
czeka_na_a := czeka_na_a-1;
end;
end;
Procedure sprawdz_b()
begin
...symetrycznie...
end;
begin
while (true) do
begin
op := GetMsg(operacja);
case op of
ChceA:
czeka_na_a := czeka_na_a+1;
ChceAlubB:
czeka_na_alubb := czeka_na_alubb+1;
ZwalniamA:
dostepnych_a := dostepnych_a+1;
end; {case}
sprawdz_a();
end;
end;
To rozwiązanie gwarantuje postęp w procesach KlientA, nie zapewnia postępu (prowadzi do zagłodzenia) dla procesów KlientAlubB.
Przydzielanie zasobu A zarówno procesom KlientA jak i KlientAlubB.
type
PrzydzielenieTyp = (PrzydzielenieNull, PrzydzielonyA, PrzydzielonyAlubB);
Process Serwer;
var
dostepnych_a: integer := X;
czeka_na_a: integer := 0;
czeka_na_alubb: integer := 0;
ostatni_a_komu_przydzielony: PrzydzielenieTyp := PrzydzielenieNull;
op: OperacjaTyp;
Procedure sprawdz_a()
begin
if (dostepnych_a>0 and (czeka_na_a>0 or czeka_na_alubb>0)) then
begin
dostepnych_a := dostepncyh_a-1;
if (czeka_na_a=0 and czeka_na_alubb>0) then
begin
SendMsg(zasob_alubb, PozwolenieA);
czeka_na_alubb := czeka_na_alubb-1;
ostatni_a_komu_przydzielony := PrzydzielenieAlubB;
end;
else if (czeka_na_a>0 and czeka_na_alubb=0) then
begin
SendMsg(zasob_a, PozwolenieA);
czeka_na_a := czeka_na_a-1;
ostatni_a_komu_przydzielony := PrzydzielenieA;
end;
else {czeka_na_a>0 and czeka_na_alubb>0}
begin
case ostatni_a_komu_przydzielony of
PrzydzielenieNull:
SendMsg(zasob_a, PozwolenieA);
czeka_na_a := czeka_na_a-1;
ostatni_a_komu_przydzielony := PrzydzielenieA;
PrzydzielenieA:
SendMsg(zasob_alubb, PozwolenieA);
czeka_na_alubb := czeka_na_alubb-1;
ostatni_a_komu_przydzielony := PrzydzielenieAlubB;
PrzydzielenieAlubB:
SendMsg(zasob_a, PozwolenieA);
czeka_na_a := czeka_na_a-1;
ostatni_a_komu_przydzielony := PrzydzielenieA;
end; {case}
end;
end;
end;
begin
while (true) do
begin
op := GetMsg(operacja);
case op of
ChceA:
czeka_na_a := czeka_na_a+1;
ChceAlubB:
czeka_na_alubb := czeka_na_alubb+1;
ZwalniamA:
dostepnych_a := dostepnych_a+1;
end; {case}
sprawdz_a();
end;
end;
To rozwiązanie gwarantuje postęp w procesach KlientA i KlientAlubB.