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.