Grupy zasobów

W systemie dostępnych jest M zasobów. W systemie działa N procesów. Każdy proces działa według schematu:

Zapisz procedury rezerwowania i zwalniania zasobów:

  1. Zapisz treść procesu P(j: 1..N) używając do synchronizacji semaforów.

  2. Zapisz treść procesu P(j: 1..N) i monitor Serwer synchronizujący dostęp do zasobów.

process P
var
  potrzebne_zasoby: array of (1..M);
begin
  while (true) do
  begin
    wlasne_sprawy();
    potrzebne_zasoby := wyznacz_potrzebne_zasoby();
    ...rezerwuj_zasoby(potrzebne_zasoby)...
    pracuj(potrzebne_zasoby);
    ...zwolnij_zasoby(potrzebne_zasoby)...
  end;  
end;

Rezerwacja grupy zasobów musi być przeprowadzona w określony sposób. Rozważmy sytuację gdy proces A chce zarezerwać zasób X a potem zasób Y, a proces B chce zarezerwować zasób Y a potem zasób X. Jeśli proces A zarezerwuje zasób X, proces B zarezerwuje zasób Y to proces A będzie czekał na zwolenienie zasobu Y a proces B będzie czekał na zwolnienie zasobu X. Taka sytuacja to zakleszczenie. Można uniknąć zakleszczenie, jeśli zasoby rezerwowane są w tej samej kolejności (np od najmniejszego do największego) - dlatego w rozwiązaniach najpierw sortujemy identyfikatory zasobów.

Semafory

var
  rezerwacja_zasobu: array[1..M] of binary_semaphore := (M times 1);

procedure rezerwuj_zasoby(potrzebne_zasoby: array[1..K] of (1..M))
var i: integer;
    zasob: (1..M);
begin
  sort(potrzebne_zasoby);
  for i:=1 to K do
  begin
    zasob := potrzebne_zasoby[i];
    P(rezerwacja_zasobu[zasob]);
  end;
end;

procedure zwolnij_zasoby(potrzebne_zasoby: array[1..K] of (1..M))
var i: integer;
    zasob: (1..M);
begin
  sort(potrzebne_zasoby);
  for i:=1 to K do
  begin
    zasob := potrzebne_zasoby[i];
    V(rezerwacja_zasobu[zasob]);
  end;
end;

process P
var
  potrzebne_zasoby: array of (1..M);
begin
  while (true) do
  begin
    wlasne_sprawy();
    potrzebne_zasoby := wyznacz_potrzebne_zasoby();
    rezerwuj_zasoby(potrzebne_zasoby);
    pracuj(potrzebne_zasoby);
    zwolnij_zasoby(potrzebne_zasoby);
  end;  
end;