background image

Wyłączenie  przerwań

– Nie działa w systemach wieloprocesorowych
– Problematyczne w systemach z ochroną
– Wykorzystywane do synchronizacji w obrębie jądra (zakładając jeden 

procesor)

Rozwiązania z czekaniem aktywnym

– Algorytm Petersona dla dwóch procesów – wymaga trzech 

zmiennych !!!

– Algorytm piekarni dla wielu procesów.
– Rozwiązania wykorzystujące specjalne instrukcje maszynowe np. 

rozkaz zamiany

Marnowany jest czas procesora. Uzasadnione gdy czas 
oczekiwania jest stosunkowo krótki (najlepiej krótszy od 
czasu przełączenia kontekstu)

Rozwiązanie sekcji krytycznej

background image

Początkowo komórki tablicy k są 
równe 1. Każdy z procesów 
kontroluje jedną komórkę tej 
tablicy. Gdy proces chce wejść do 
sekcji krytycznej, to ustawia 
komórkę na 0, aż do chwili wyjścia 
z sekcji krytycznej. 

Zmienna czyja_kolej jest 
początkowo równa 1. Łamie ona 
symetrię między procesami. W 
sytuacji, gdy obydwa procesy chcą 
wejść do sekcji krytycznej zmienna 
ta rozstrzyga, który powinien 
ustąpić drugiemu. 
Zakładamy, że procesy mają 
numery 1 i 2, i każdy proces 
pamięta swój numer na zmiennej 
lokalnej p. 

Rozwiązanie jest poprawne, ale 
jednak jest ograniczone do dwóch 
procesów, 
proces oczekujący oczekuje 
aktywnie
, tzn. ciągle sprawdza 
warunek, czy dane zdarzenie już 
zaszło.

Wspólne zmienne

var
  k: array [1..2] of 0..1;
  czyja_kolej: 1..2;

Sekcja wejściowa: 
  k [p] := 0;
  while k [3 - p] = 0 do
  begin
    if czyja_kolej ≠ p then
      begin (*Ustąp drugiemu*)
        k [p] := 1;
       while czyja_kolej ≠ p do;
        k [p] := 0
      end;
  end    

Sekcja wyjściowa: 
  k [p] := 1;
  czyja_kolej := 3 - p;

background image

Procesy chcące wejść do sekcji 
krytycznej "pobierają numery". W 
tablicy wybieranie proces zaznacza, 
iż jest właśnie w trakcie pobierania 
numeru, a pobrany numer 
zapamiętuje w tablicy numery. 
Proces wchodzi do sekcji krytycznej, 
gdy upewni się, że jest pierwszy w 
kolejce. Po wyjściu z sekcji krytycznej 
proces "wyrzuca numer", tzn. 
zapisuje w tablicy numery wartość 0. 
Mamy gwarancję, że kolejne numery 
tworzą ciąg niemalejący, możliwe są 
w nim jednak powtórzenia. Jeżeli dwa 
procesy otrzymają ten sam numer, to 
pierwszeństwo ma proces o niższym 
numerze (p). Możemy więc 
powiedzieć, że procesy wchodzą do 
sekcji krytycznej w porządku 
leksykograficznym par (numer, 
numer procesu). 
Algorytm piekarniany jest bardziej 
ogólny niż algorytm Dekkera, lecz 
również nie jest wolny od wad -  
nadal mamy do czynienia z 
aktywnym oczekiwaniem, liczba 
procesów jest ograniczona przez 
stałą n

Wspólne zmienne – alg. piekarniany

var

  wybieranie: array [1..n] of boolean;

  numerek: array [0..n-1] of integer;

Sekcja wejściowa:

  wybieranie[p] := true;

  numerek[p] := max(numerek[1..n]) + 1 

  wybieranie[p] := false;

  for j := 1 to n do

  begin

    while wybieranie[j] do;

    while numerek[j]≠0 and

         (numerek[j],j)<(numerek[p],p) 
do;  

  end;

Sekcja wyjściowa: 

  numerek [p] := 0;

background image

Jest to mechanizm synchronizacji  przypominający działanie 
semafora kolejowego. Wyobraźmy sobie wielotorową magistralę 
kolejową, która na pewnym odcinku zwęża się do k torów. 
Pociągi jeżdżące magistralą to procesy. Zwężenie to uogólnienie 
sekcji krytycznej. Na zwężonym odcinku może znajdować się na 
raz maksymalnie k pociągów, każdy na oddzielnym torze. 
Podobnie jak w przypadku sekcji krytycznej, każdy oczekujący 
pociąg powinien kiedyś przejechać i żaden pociąg nie powinien 
stać, jeżeli jest wolny tor. Semafor to specjalna zmienna 
całkowita, początkowo równa k. Specjalna, ponieważ (po 
zainicjowaniu) można na niej wykonywać tylko dwie operacje: 

P - Jeżeli semafor jest równy 0 (semafor jest opuszczony), to 
proces wykonujący tę operację zostaje wstrzymany, dopóki 
wartość semafora nie zwiększy się (nie zostanie on 
podniesiony). Gdy wartość semafora jest dodatnia (semafor jest 
podniesiony), to zmniejsza się o 1 (pociąg zajmuje jeden z k 
wolnych torów). 

V - Wartość semafora jest zwiększana o 1 (podniesienie 
semafora). Jeżeli jakiś proces oczekuje na podniesienie 
semafora, to jest on wznawiany, a semafor natychmiast jest 
zmniejszany. 

Semafory

background image

Opuszczanie semafora

procedure P(var s: Semaphore)
begin
while s = 0 do nic;
s := s - 1; 
end;

Podnoszenie semafora

procedure V(var s: Semaphore)
begin
s := s + 1; 
end;

Operacje  semaforów

background image

Jeżeli procesy mogą przebywać na raz więcej niż w jednej sekcji 
krytycznej, to musimy zwrócić uwagę na możliwość 
zakleszczenia
Załóżmy: 

Semafory S i Q, każdy związany z jedną sekcją krytyczną.
Procesy: P1 i P2 - każdy z nich chce wejść równocześnie do 
obydwu sekcji krytycznych.

Jeżeli są one zaimplementowane następująco: 

P1

P2:

    P(S);

    P(Q);

    P(Q); 

    P(S);

  Sekcje krytyczne

  Sekcje krytyczne

    V(Q); 

    V(S);

    V(S);

    V(Q);

to możliwy jest następujący scenariusz: 

Proces P1 opuszcza semafor S, po czym proces P2 opuszcza semafor Q
Wówczas proces P1 czeka w nieskończoność na podniesienie semafora 
Q, a proces P2 na podniesienie semafora S. Sytuację taką nazywamy 
właśnie zakleszczeniem. W przedstawionym przykładzie rozwiązaniem 
jest opuszczanie semaforów w obu procesach w tej samej kolejności. 

Semafory

background image

Monitor to rodzaj klasy, której metody stanowią sekcję 
krytyczną.

Atrybuty monitora są dostępne jedynie wewnątrz (metod) 
monitora. Konstrukcja monitora zapewnia, że tylko jeden proces 
na raz może znajdować się w monitorze. Pozostałe procesy 
oczekują w kolejce (FIFO). 

Jeśli jakiś proces chce wejść do monitora, który jest właśnie 
zajęty, to jest on wstawiany na koniec kolejki procesów 
oczekujących na wejście do monitora. Jeśli proces opuszcza 
monitor, a inne procesy czekają w kolejce na wejście do 
monitora, to pierwszy proces z kolejki wchodzi do monitora.

Udostępniają one dodatkowo kolejki procesów typu condition. 
Kolejki takie mogą być używane tylko wewnątrz monitorów. Są 
to kolejki FIFO, udostępniające dwie operacje: 
wait - powoduje wstrzymanie procesu i wstawienie go na 
koniec kolejki, 
signal - powoduje wznowienie pierwszego procesu z kolejki, o 
ile kolejka nie jest pusta. 
 

Monitory

background image

Rodzaje zmiennych:

 zamek - umożliwiająca implementację wzajemnego 
wykluczania,

 Operacje:

– lock - zajęcie (zaryglowanie) zamka
– unlock - zwolnienie (odryglowanie) zamka
– trylock - nieblokująca próba zajęcia zamka

– zmienna warunkowa - umożliwia usypianie i budzenie 
wątków.

Operacje:

– wait - uśpienie wątku,
– signal - obudzenie jednego z uśpionych 
wątków
– broadcast - obudzenie wszystkich uśpionych
wątków

Zmienne synchronizujące muszą być współdzielone
przez synchronizowane wątki. Zanim zmienna zostanie 
wykorzystana do synchronizacji musi zostać 
zainicjalizowana.

Zmienne synchronizujące


Document Outline