home 
news 
thread sync 
sync problems 
project intro 
assignment 1 
assignment 2 
assignment 3 
resources 
examples 
rules 
submit howto 
   
 

Thread synchronization / Sincronizarea firelor de executie

In prima parte a laboratorului vom invata sa utilizam citeva mecanisme pentru sincronizarea firelor de executie. Cu unele v-ati intilnit deja in materiile studiate anterior, chiar daca implementarile au fost diferite: monitoarele din Java presupun lacate (obiecte synchronized) si variabile de conditie (wait/notify) iar semafoarele le-ati studiat la "Sisteme de operare 1".

In continuare vom trece in revista semafoarele, lacatele si variabilele de conditie definite in standardul POSIX. Descrierea lor nu este completa si de aceea studentii trebuie sa citeasca paginile de manual corespunzatoare. De asemenea, o discutie mai generala si mai completa legata de mecanismele de sincronizare va avea loc la curs.

Posix semaphores / Semafoare POSIX

Pagini de manual: sem_init(3), sem_destroy(3), sem_post(3), sem_wait(3), sem_overview(7).

Semafoarele sunt un mecanism de sincronizare inventat de Dijkstra. Ele sunt obiecte avind o stare si doua operatii de baza. Astfel, un semafor va avea o valoare (stare) intreaga nenula si operatiile atomice P si V.

Operatia P decrementeaza semaforul in mod atomic. Daca valoarea semaforului este zero, operatia va bloca firul apelant.

Operatia V incrementeaza semaforul in mod atomic. Daca valoarea semaforului este zero si exista fire blocate in coada de asteptare a semaforului, V va debloca unul din firele in asteptare, lasind semaforul cu valoarea zero (echivalent: in mod atomic V va incrementa semaforul, va debloca unul din fire care va continua operatia P decrementind semaforul, in final valoarea acestuia fiind zero).

Semafoarele reprezinta un mecanism flexibil pentru sincronizarea proceselor. Exemplele sunt doar doua situatii in care acestea pot fi folosite.

Numele operatiilor difera mult in diverse implementari. Tabela alaturata da citeva exemple. P si V sint denumirile originale, asa cum au fost definite de catre Dijkstra.

operatia de decrementareoperatia de incrementare
PV
waitsignal
waitpost
downup

Cititi si rulati exemplul de excludere mutuala folosind semafoare.

Un alt mod de utilizare a semafoarelor se poate gasi in exemplul de la variabile de conditie.

pthread mutexes / Lacate pthread

Pagini de manual: pthread_mutex_init(3), pthread_mutex_lock(3), pthread_mutex_unlock(3) pthread_mutex_destroy(3), pthread_mutexattr_init(3), pthread_mutexattr_gettype(3), pthread_mutexattr_settype(3), pthread_mutexattr_destroy(3).

Lacatele (locks sau mutexes) sint un mecanism de sincronizare asemanator semafoarelor. Ele sunt folosite pentru excludere mutuala - de unde numele de mutex. Lacatele au o stare cu doua valori posibile (locked si unlocked) si doua operatii (lock sau acquire si unlock sau release).

La creare, un lacat este in starea "deschis". Operatia lock pe un lacat deschis va face ca lacatul sa treaca in starea "inchis" iar firul care inchide lacatul se spune ca il detine. Operatia lock efectuata asupra unui lacat inchis va bloca firul apelant.

Operatia unlock efectuata asupra unui lacat inchis, apelata de firul ce detine lacatul, va debloca unul din firele de executie blocate in asteptare in urma unui lock pe acel lacat. Firul deblocat va fi cel care detine lacatul in continuare. Daca nu exista fire in asteptare, lacatul va fi trecut in starea unlocked si nici un fir nu va mai detine lacatul.

Daca un fir de executie efectueaza operatia unlock pe un lacat deschis sau detinut de alt fir, ea va returna eroare. De asemenea, operatia lock efectuata asupra unui lacat deja inchis si detinut de firul apelant va returna eroare.

In Linux (si alte citeva sisteme asemanatoare UNIX), exista trei tipuri de lacate: "fast", "error checking" si "recursive". Descrierea de mai sus se refera la tipul "error checking" pe care il vom utiliza. Cititi paginile de manual pentru o descriere completa.

Cititi si rulati exemplul de excludere mutuala folosind lacate.

pthread condition variables / Variabile de conditie pthread

Pagini de manual: pthread_cond_init(3), pthread_cond_wait(3), pthread_cond_signal(3), pthread_cond_broadcast(3), pthread_cond_destroy(3).

Variabilele de conditie sunt un mecanism prin care un fir de executie poate astepta un eveniment (indeplinirea unei conditii) generat sau sesizat de un alt fir. Spre deosebire de celelalte doua mecanisme, variabilile de conditie nu au stare.

Exista trei operatii de baza ce pot fi aplicate pe un asemenea obiect: wait, signal si broadcast. Operatia wait face ca firul apelant sa se blocheze in asteptarea aparitiei evenimentului asociat variabilei de conditie. Celelalte doua operatii permit unui fir de executie sa semnaleze generarea (sau sesizarea) evenimentului sau indeplinirea conditiei asociate. Diferenta dintre ele consta in faptul ca signal va anunta (va debloca) un singur fir din coada de asteptare iar broadcast va debloca toate firele.

Spre deosebire de semafoare sau lacate, la care evenimente anterioare (unlock respectiv post) influenteaza operatiile care pot genera blocarea firului (lock respectiv wait), la variabile de conditie o operatie wait nu va fi influentata de un signal sau broadcast anterior. Firul se va bloca intotdeauna in asteptarea unui eveniment ulterior apelului wait si se presupune, de aceea, ca firul va verifica indeplinirea conditiei asociate variabilei, atunci cind este cazul, inainte de a apela wait. Desigur pot exista situatii cind dorim sa asteptam un eveniment ulterior (de exemplu urmatoarea expirare a unui temporizator) fara a mai fi nevoie de vreo verificare.

Cititi si rulati exemplul de sincronizare folosind variabile de conditie.

O problema rezolvata: cititori - scriitori

Problema: un program este compus din mai multe fire de executie. N fire sint cititori iar M fire scriitori. Cititorii citesc o variabila globala (resursa partajata) si afiseaza valoarea citita. Sciitorii scriu in acea varibila (de exemplu, un identificator).

Desigur, un singur scriitor are voie sa acceseze la un moment dat resursa partajata. Insa aceeasi restrictie nu se impune si cititorilor. Astfel, oriciti cititori au voie sa citeasca resursa partajata simultan.

Cititi si rulati rezolvarea corecta, cit si una gresita (doua greseli, gasiti-le!)