Rozpatrzmy teraz przydzielanie dwóch zasobów: A i B.
Przydzielanie zasobu A w sposób wyłączny i zasobu B w sposób wyłączny - prowadzi to do zagłodzenia procesów typu KlientAlubB, gdyż nigdy żaden zasób nie jest przydzielany tym procesom.
Przydzielanie zasoubu a w sposób przemienny i zasobu B w sposób wyłączny - żadna grupa procesów nie jest głodzona. Może się jednak zdażyć, że procesy z grupy KlientAlubB niepotrzebnie czekają. Dzieje się tak gdy nie można przydzielić zasobu A (bo już używa go X procesów), ale możnaby przydzielić zasób B (gdyż używa go mniej niż Y procesów). W tym algorytmie zasób B nie jest przydzielany procesom grupu KlientAlubB nawet gdy jest on dostępny. Nie prowadzi to jednak do ich zagłodzenia bo założyliśmy że (X>0) i zapewnienie postępu na zasobie a jest zagwarantowane dla tej grupy procesów - używamy algorytmu przemiennego.
Przydzielanie zasobu A w sposób przemienny i zasobu B w sposób przemienny - wtedy żadna grupa procesów nie jest głodzona. Nie zachodzi sytuacja taka (jak w porzednim podejściu), że proces nie korzysta z zasobów z których mógłby korzystać mimo że są dostępne.
type PrzydzielenieTyp = (PrzydzielenieNull, PrzydzielonyA, PrzydzielonyAlubB, PrzydzielonyB); Process Serwer; var dostepnych_a: integer := X; dostepnych_b: integer := Y; czeka_na_a: integer := 0; czeka_na_b: integer := 0; czeka_na_alubb: integer := 0; ostatni_a_komu_przydzielony: PrzydzielenieTyp := PrzydzielenieNull; ostatni_b_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; 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; ChceB: czeka_na_b := czeka_na_b+1; ChceAlubB: czeka_na_alubb := czeka_na_alubb+1; ZwalniamA: dostepnych_a := dostepnych_a+1; ZwalniamB: dostepnych_b := dostepnych_b+1; end; {case} sprawdz_a(); sprawdz_b(); end; end;
Rozwiązanie ma pewien mały mankament. Rozpatrzmy sytuację, gdy działają tylko procesy KlientAlubB, i załóżmy, że jest ich mniej niż X wtedy będą one korzystały tylko z zasoby A. Jest to priorytet dla zasobu A, w niektórych sytuacjach takie zachowanie może być nieoczekiwane. Rozwiązaniem tego problemu jest zapamiętywanie jaki zasób ostatnio został przydzielony procesowi z grupy KlientAlubB i w pierwszej kolejności przydzielanie innego zasobu następnemu procesowi z tej grupu. Osiągamy to pamiętając jaki zasób przydzieliliśmy ostatnio procesowi tej grupy i starając się najpierw przydzielić drugi zasób, a dopiero potem z ten sam zasób.
type PrzydzielenieTyp = (PrzydzielenieNull, PrzydzielonyA, PrzydzielonyAlubB, PrzydzielonyB); Process Serwer; var dostepnych_a: integer := X; dostepnych_b: integer := Y; czeka_na_a: integer := 0; czeka_na_b: integer := 0; czeka_na_alubb: integer := 0; ostatni_a_komu_przydzielony: PrzydzielenieTyp := PrzydzielenieNull; ostatni_b_komu_przydzielony: PrzydzielenieTyp := PrzydzielenieNull; ostatni_alubb_przydzielony_przez: 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; ostatni_alubb_przydzielony_przez := PrzydzielenieA; PrzydzielenieAlubB: SendMsg(zasob_a, PozwolenieA); czeka_na_a := czeka_na_a-1; ostatni_a_komu_przydzielony := PrzydzielenieA; end; {case} end; 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; ChceB: czeka_na_b := czeka_na_b+1; ChceAlubB: czeka_na_alubb := czeka_na_alubb+1; ZwalniamA: dostepnych_a := dostepnych_a+1; ZwalniamB: dostepnych_b := dostepnych_b+1; end; {case} case (ostatni_alubb_przydzielony_przez) of PrzydzielenieNull: PrzydzielenieA: sprawdz_b(); sprawdz_a(); PrzydzielenieB: sprawdz_a(); sprawdz_b(); end; {case} end; end;