Transcript 06.Semafory

Jarosław Kuchta
Semafory
Operacje


podniesienie semafora
opuszczenie semafora

Operacje są niepodzielne
(atomowe), tzn. że żadna z
tych operacji nie może zostać
przerwana.
Rodzaje semaforów


ogólny
binarny


ograniczony
uogólniony
Semafor ogólny
(definicja klasyczna Dijkstry)

Zmienna całkowita S:



podniesienie – V(S): S = S + 1;
opuszczenie – P(S): while (S<=0); S = S – 1;
Nie spełnia warunku niepodzielności
Semafor ogólny
(definicja praktyczna BenAriego)

Zmienna całkowita S:

podniesienie – V(S):
if (są procesy wstrzymane podczas opuszczania S)
wznów jeden z nich;
else
S = S +1;

opuszczenie – P(S):
if (S>0)
S = S – 1;
else
wstrzymaj;

Spełnia warunek niepodzielności
Konstrukcja semafora
Opuszczenie
Podniesienie
Proces A
Proces B
P(S):
V(S):
S=0
S=S-1
ktoś czeka
S=S+1
Semafor binarny
(definicja klasyczna)

Zmienna logiczna S:


podniesienie – VB(S): S = 1;
opuszczenie – PB(S): while (S==1); S = 0;
Semafor binarny
(definicja praktyczna)

Zmienna logiczna S:

podniesienie – VB(S):
if (są procesy wstrzymane podczas opuszczania S)
wznów jeden z nich;
else
S = 1;

opuszczenie – PB(S):
if (S==1)
S = 0;
else
wstrzymaj;
Semafor binarny a ogólny




Semafor binarny NIE jest szczególnym przypadkiem
semafora ogólnego.
Semafor binarny nie pamięta liczby operacji
podniesienia.
Semafor binarny może zastąpić ogólny, gdy realizuje
wzajemne wykluczanie.
Podniesienie już podniesionego semafora binarnego
jest błędem.
Semafor dwustronnie
ograniczony

Zmienna całkowita S z zakresu (0..N):

podniesienie – V(S):
if (S==N)
wstrzymaj;
else if (są procesy wstrzymane podczas opuszczania S)
wznów jeden z nich;
else
S = S + 1;

opuszczenie – P(S):
if (S==0)
wstrzymaj;
else if (są procesy wstrzymane podczas opuszczania S)
wznów jeden z nich;
else
S = S – 1;
Semafor uogólniony

Operacje podniesienia i opuszczenia mają dodatkowy operand n

podniesienie – V(S, n):
if (są procesy wstrzymane podczas opuszczania S o m)
{
wznów jeden z nich;
S = S – m + n;
}
else
S = S + n;

opuszczenie – P(S, n):
if (S >= n)
S = S – n;
else
wstrzymaj;
Jednoczesne operacje
semaforowe

Koniunktywna

PAND (S1, S2):
if (S1 > 0 && S2 > 0)
{
S1 = S1 – 1;
S2 = S2 – 1;
}
else
wstrzymaj;

Alternatywna

POR (S1, S2):
if (S1 > 0 || S2 > 0)
{
S1 = S1 – 1;
S2 = S2 – 1;
}
else
wstrzymaj;
Przykłady



Producenci i konsumenci
Czytelnicy i pisarze
Pięciu filozofów
1 producent i 1 konsument
Semaphore Wolne = N;
Semaphore Pełne = 0;
Dane[] bufor = new Dane[N];
void Producent ()
{
Dane dane;
int i = 0;
while (true)
{
Produkuj (out dane);
P(Wolne);
bufor [i] = dane;
i = (i + 1) % N;
V(Pełne);
}
}
void Konsument ()
{
Dane dane;
int j = 0;
while (true)
{
P(Pełne);
dane = bufor [j];
j = (j + 1) % N;
V(Wolne);
Konsumuj (dane);
}
}
Wielu producentów i
konsumentów
Semaphore Wolne = N;
Semaphore Pełne = 0;
Dane[] bufor = new Dane[N];
int j = 0; int k = 0
BinarySemaphore i_S = 1;
BinarySemaphore j_S = 1;
void Producent ()
{
Dane dane;
while (true)
{
Produkuj (out dane);
P(Wolne);
PB(i_S);
bufor [i] = dane;
i = (i+1) % N;
VB(i_S);
V(Pełne);
}
}
void Konsument ()
{
Dane dane;
while (true)
{
P(Pełne);
PB(j_S);
dane = bufor [j];
j = (j+1) % N;
VB(j_S);
V(Wolne);
Konsumuj (dane);
}
}
Czytelnicy i pisarze
int M; // liczba czytelników
int P; // liczba pisarzy
Semaphore Wolne = N; // liczba miejsc w czytelni
BinarySemaphore W = 1; // wzajemne wykluczanie się pisarzy
void Czytelnik ()
{
while (true)
{
Własne_Sprawy();
P(Wolne);
Czytanie();
V(Wolne);
}
}
void Pisarz ()
{
while (true)
{
Własne_Sprawy();
PB(W);
// Pisarz stopniowo zajmuje miejsca
// w czytelni
for (int j=0; j<M; j++) P(Wolne);
Pisanie();
VB(W);
}
}
Pięciu filozofów
(z możliwością zagłodzenia)
BinarySemaphore[] Pałeczki = new BinarySemaphore[] {1, 1, 1, 1, 1};
void Filozof(int i)
{
while (true)
{
Myślenie();
PB(Pałeczki, i);
PB(Pałeczki, (i+1) % 5);
Jedzenie();
VB(Pałeczki, i);
VB(Pałeczki, (i+1) % 5);
}
}
Pięciu filozofów
(z lokajem)
BinarySemaphore[] Pałeczki = new BinarySemaphore[] {1, 1, 1, 1, 1};
Semaphore Lokaj = 4;
void Filozof(int i)
{
while (true)
{
Myślenie();
P(Lokaj);
PB(Pałeczki, i);
PB(Pałeczki, (i+1) % 5);
Jedzenie();
VB(Pałeczki, i);
VB(Pałeczki, (i+1) % 5);
V(Lokaj);
}
}