Documente Academic
Documente Profesional
Documente Cultură
Sincronizarea threadurilor
(continuare)
Cursul 7: Recapitulare
Solutii de sincronizare
Hardware
Operatii load/store
load: incarca date din memorie, prin copiere din memorie in registri
store: salveaza date in memorie, prin copiere din registri in memorie
Dezactivarea intreruperilor
Test&set
API de nivel inalt
Lacate
Semafoare
Monitoare
Send/Receive
Cursul 7: Recapitulare
Locks (lacate)
Sa presupunem ca avem o implementare a unui lacat, acesta va avea
urmatoarele metode:
Lock.Acquire() – asteapta pana cand lacatul este liber, apoi lacatul
este preluat
Lock.Release() – deblocare, “trezirea” tuturor threadurilor care
asteapta
Operatiile trebuie sa fie atomice – daca doua threaduri asteapta un lacat si
ambele observa ca acesta este liber, doar un thread va reusi sa preia
lacatul
Problema “pre mult lapte” se usureaza:
milklock.Acquire();
if (nomilk)
buy milk;
milklock.Release();
Reamintim ca segmentul de cod dintre Acquire() si Release() este
“Sectiunea critica”
Cursul 7: Recapitulare
Dezactivarea intreruperilor
■ Implementare simplista a lacatelor:
LockAcquire { disable Ints; }
LockRelease { enable Ints; }
//implementare cu semafoare
S=1
Semaphore. P() //S.Wait() Semaphore. P() //S.Wait()
if (noMilk){ if (noMilk){
buyMilk(); buyMilk();
} }
Semaphore.V() //S.Signal() Semaphore.V() //S.Signal()
Utilizarile semafoarelor
• Excludere mutuala (valoarea initiala = 1)
• Denumit si “Semafor binar”.
• Poate fi folosit pentru excludere mutuala:
semaphore.P();
// Sectiune critica aici
semaphore.V();
• Constrangeri de planificare (valoarea initiala = 0)
• Lacatele se descurca bine in problema excluderii mutuale, dar ce se
intampla atunci cand doresti ca un thread sa astepte un eveniment?
• Exemplu: sa presupunem ca trebuie implementat ThreadJoin() care
trebuie sa astepte terminarea unui alt thread:
Initial value of semaphore = 0
ThreadJoin {
semaphore.P();
}
ThreadFinish {
semaphore.V();
}
• Shared pool de resurse (valoare initiala n):
• ex server Web cu un listener si un pool de threaduri de tip workers (n)
Exemplul 1 de lucru cu semafoare
S=2
Thread 1 Thread 2
S.P() S.P()
S.P() S.V()
S.V()
S.V()
Valoare Coada stare T1 stare T2
T Operatie 2 goala executie executie
T1 S.P()
T2 S.P()
T1 S.P()
T2 S.V()
T1 S.V()
T1 S.V()
Exemplul 1 de lucru cu semafoare
S=2
Thread 1 Thread 2
S.P() S.P()
S.P() S.V()
S.V()
S.V()
Valoare Coada stare T1 stare T2
T Operatie 2 goala executie executie
T1 S.P() 1 goala executie executie
T2 S.P() 0 goala executie executie
T1 S.P() 0 T1 blocat executie
T2 S.V() 1 T1 executie executie
T1 S.V() 0 goala executie executie
T1 S.V() 1 goala executie executie
2 goala executie executie
Exemplul 2 de lucru cu semafoare
S1=0; S2=0
Thread A Thread B
buyMilk() buyCake()
S1.V() S2.V()
S2.P() S1.P()
eat() eat()
Problema producator-consumator cu buffer
comun
• Definirea problemei
• Producatorul introduce elemente intr-un buffer comun
• Consumatorul le foloseste
• Exista nevoia de sincronizare pentru a coordona producatorul si
consumatorul
• Pentru a se evita activitati succesive P/C, este necesara crearea
unui buffer cu o marime fixa intre P si C
• Accesul la acest buffer trebuie sincronizat
• Producatorul trebuie sa astepte daca bufferul este plin
• Consumatorul trebuie sa astepte daca buffer-ul este gol
• Exemplu: Automatul de cola
• Producatorul poate pune un numar limitat de cola in automat
• Consumatorul nu poate consuma cola daca automatul este gol
AddToQueue(item) {
lock.Acquire(); // Get Lock
queue.enqueue(item); // Add item
dataready.signal(); // Signal any waiters
lock.Release(); // Release Lock
}
RemoveFromQueue() {
lock.Acquire();// Get Lock
while (queue.isEmpty()) {
dataready.wait(&lock);
// If nothing, sleep and release lock }
item = queue.dequeue();// Get next item
lock.Release(); // Release Lock
return(item);
}
Solutia problema P/C cu monitoare
TEMA
Sfarsitul cursului 8