Professional Documents
Culture Documents
Semafori
Dosadanja reenja nije lako primeniti na kompleksnije sluajeve sinhronizacije procesa.
U tom kontekstu uvodi se novi metod, koji se naziva semafor. Semafor je nenegativna-integer
promenljiva na koju je pored inicijalizacije, mogue primeniti samo dve vrste nedeljivih
(atomic) operacija. To su signal i wait operacija.
Klasina definicija wait operacije na semaforom S je
wait (S):
while(S<=0) do no-op;
S--;
Klasina definicija signal operacije na semaforom S je
signal (S):
S++;
Operacije wait i signal nad semaforom S su nedeljive, moraju se izvrti do kraja. Dok jedan
proces modifikuje vrednost semafora, nijedan drugi proces ne moe istrovremeno modifikovati
vrednost istog semafora.
Semafori se mogu podeliti u dve grupe:
jaki semafori : oni u kojima svi procesi koji ekaju na primitivi wait smeteni u red
ekanja po FIFO principu(onaj koji najdue eka prvi dobija pravo na izvravanje).
slabi semafori : oni kod kojih svi procesi koji ekaju na semafor nastavljaju sa
izvravanjem po proizvoljnom redosledu.
opte (brojake)
binarne(0,1)
Binarni semafori su specijalna klasa semafora, ija vrednost moe biti samo 0 ili 1. Semafori
koji nemaju ovaj limit nazivaju se brojaki semafori (counting semaphor). Birnarni semafori su
laki za implementaciju. Evo jednog primera kako se od 2 binarna semafora S1 i S2 i jedne
celobrojne promenljive C, moe realizovati brojaki semafor S:
Korienje semafora
Problem kritine sekcije moemo razreiti pomou semafora mutex (mutual exclusion). U
sluaju da imamo n procesa, problem kritine sekcije razreiemo na sledei nain:
semaphore mutex; /*initially mutex = 1*/
do{
wait(mutex);
critical section
signal(mutex);
remainder section
} while (1);
PRIMER 6-1.cm
// Program demonstrira
// upotrebu semaphora mutex za resenje uzajamnog iskljucivanja
semaphore mutex;
void say_hello (char id) {
wait( mutex );
cout << id <<" "<<id <<" "<<id <<" "<<id <<" "<<id <<" "<< endl;
signal( mutex );
}
main() {
initialsem( mutex, 1 );
cobegin
{
say_hello( 'A'); say_hello('B'); say_hello( 'C');
}
cout << "KRAJ" << endl;
}
Ulazna sekcija svih procesa se razreava sa wait operacijom. Samo jedan proces proi e na
semaforu mutex, ija je inicijalna vrednost = 1, oborie mu vrednost na 0 i ui u svoju kritinu
sekciju. Svi ostali procesi iza toga, bie zaglavljeni na semaforu wait(mutex). Kada proces
napusti kritinu sekciju, oslobodie semafor sa komandom signal(mutex).
Semafori se mogu primeniti i za razne druge probleme u sinhronizaciji kod konkurentnih
procesa. Na primer ako imamo proces P1 sa naredbom S1 i proces P2 sa naredbom S2.
Pretpostavimo da se zahteva da se S2 naredba izvri tek nakon to se kompletira naredba S1.
Problem emo razreiti preko semafora synch, (inicijalno = =0) na sledei nain:
P1
P2
...
....
S1
wait(synch)
signal(synch) S2
PRIMER 6-2.cm
// Program demonstrira
// upotrebu semaphora za sinhronizaciju procesa
// proces C krece tek sa izvrsavanjem kada se A i B zavrse
semaphore mutex;
semaphore A_finish, B_finish;
4
PRIMER 6-3.cm
/*Demonstrira ogranicen pristup resursima */
const int m = 5;
semaphore countsem;
void val1 (char id){
int i;
for ( i = 1; i <= m; i = i + 1) {
wait(countsem);
cout <<" 1"<<id<<" 1"<<id<<" 1"<<id
<<" 1"<<id<<" 1"<<id<<" 1"<<id<<" 1"<<id <<endl;
signal (countsem);
}
}
void val3 (char id){
int i;
for ( i = 1; i <= m; i = i + 1) {
wait(countsem);
wait(countsem);
wait(countsem);
cout <<" 3" <<id<<" 3"<<id<<" 3" <<id<<" 3" <<id
<<" 3"<<id<<" 3" <<id<<" 3"<<id<<endl;
signal (countsem);
signal (countsem);
signal (countsem);
}
}
main(){
initialsem(countsem, 5 );
cout <<endl;
cobegin {
val1 ( 'a'); val1 ('b'); val1 ( 'c');
val3('D'); val3('E');
}
cout<< " Kraj"<<endl;
}
Wait operacija dekremetira vrednost semafora i ako je posle toga ona negativna, stavlja proces
u listu procesa koji ekaju na semafor, a blokira proces, to je ilustrovano u sledeem kodu:
wait(S){
S.value--;
if (S.value < 0) {
add this process to S.L;
block();
}
}
//
Signal operacija inkrementira vrednost semafora i ako je posle toga ona negativna ili 0, ukljanja
jedan od procesa iz liste, koga budi sa wakeup() i prebacuje u red ekanja za spremne procese,
to je ilustrovano u sledeem kodu:
signal(S) {
S.value++;
if (S.value <= 0) {
remove a process P from S.L;
wakeup(P); #but which one FIFO, LIFO, priority
}
}
Ovo je prvo reenje koje zahteva intervenciju operativnog sistema, koji ima 2 sistemska poziva
block() ili sleep() i wakeup(). Sva dosadanja reenja su bila softverska ili programerska ili
hardverska ali bez upotrebe operativnog sistema. Zapaa se da u proirenoj definiciji, vrednost
semafora moe biti negativna, to ukazuje da vei broj procesa eka na semafor, a signal
operacija po nekom kriterijumu u takvim sluajevima budi neki od uspavanih procesa. I u
proirenoj definiciji semafora, wait i signal moraju ostati nedeljive operacije.
Monitori
Monitori predstavljaju takoe konstrukciju visokog nivoa koja slui za sinhronizaciju.
Monitor se karakterie skupom programerski definisanih operatora. Reprezentacija monitora
sastoji se od deklaracije promenljivih, ije vrednosti definiu stanje monitora, i procedura i
funkcija unutar monitora. Sintaksa monitora je prikazana na sledeoj slici:
monitor monitor-name {
shared variable declarations
procedure body P1 () {
...
}
procedure body P2 () {
...
}
procedure body Pn () {
...
}
{
initialization code
}
}
Lokalne promenjive u monitiru su vidljive samo unutar monitora.
Konstrukcija monitora dozvoljava da samo jedan proces bude aktivan u monitoru. Monitor
omoguava sinhronizaciju, tako da programer ne treba da pie kod za sinhronizaciju, eksplicitno.
Ali za neke sluajeve, potrebni su dodatni sinhronizacioni mehanizmi, koji dozvojavaju uslovne
konstrukcije. Ako su one potrebne programeru, on treba da definie svoje promenljive, koje se
nazivaju uslovne promenljive:
condition x, y;
Jedine opracije koje mogu da se izvode sa ovim promenljivim su wait i signal. Operacija
x.wait ();
znai da proces koji je pozvao operaciju se suspenduje, blokira, sve dok drugi proces ne pozove
kontra operaciju:
x.signal ();
Operacija x.signal e odblokirati tano jedan blokirani proces. Ako nema blokiranih procesa,
signal operacija ne radi nita, za razliku od signal operacije na semaforu, koja uvek
9
PRIMER 6-4.cm
Procedure monV() i monP() u monitoru su napisane da odrade isti posao kao i signal i wait
operacije kod semafora. One se koriste kao i funkcije kod semafora. Program probati nekoliko
puta i prokometarisati rezultate.
/*Implementacija monitora preko semafora */
const int m = 5;
int sum; //deljeni resurs
monitor monSemaphore {
int semvalue;
condition notbusy;
void monP() {
10
if (!semvalue)
waitc(notbusy);
else
semvalue--;
}
void monV() {
if (empty(notbusy))
semvalue++;
else
signalc(notbusy);
}
}
init{semvalue = 1;}
//kraj monitora
11