Zasoby

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:

KlientA

procesy korzystające z zasobu A

KlientB

procesy korzystające z zasobu B

KlientAlubB

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.

Tylko zasób A

Rozpatrzmy najpierw problem przydzielania tylko zasobu A procesom KlientA i KlientAlubB.

Algorytm wyłączny

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.

Algorytm przemienny

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.