- blocat: daca se apeleaza release() se trece in starea neblocat
- - neblocat (este creat neblocat): daca se apeleaza acquire() se trece in starea blocatExemplu: Acelasi program de mai sus, insa cu id-urile threadurilor afisate ordonat (se foloseste Lock pentru ca in momentul afisarii zona sa fie exclusiv a firului de executie si sa nu poata interfera un alt thread)
In Python, un obiect de tip event are un flag intern, initial setat pe false
. Acesta poate fi setat pe true
cu functia set()
si resetat folosind clear()
. Pentru a verifica starea flag-ului, se apeleaza functia isSet()
.
Un alt thread poate folosi metoda wait([timeout])
pentru a astepta ca un eveniment sa se intample (ca flag-ul sa devina true
): daca in momentul apelarii wait()
, flag-ul este true
, thread-ul apelant nu se blocheaza, dar daca este false
se blocheaza pana la setarea eventului. De altfel, la un set()
, toate thread-urile care asteptau event-ul cu wait()
vor fi notificate (si eligibile deci pentru a rula).
O variabila de tip conditie (Condition) este asociata cu un obiect mutex Lock. Acesta poate fi transmis ca parametru atunci cand mai multe variabile condition partajeaza un lock sau poate fi creat implicit.
Metodele prezente sunt acquire()
si release()
care le apeleaza pe cele corespunzatoare lock-ului si mai exista functiile wait()
, notify()
si notifyAll()
, apelabile doar daca s-a reusit obtinerea lock-ului:
- - metoda
wait()
elibereaza lock-ul si se blocheaza in asteptarea unei notificari - - metoda
notify()
deblocheaza un singur thread aflat in asteptare - - metoda
notifyAll()
deblocheaza toate thread-urile care asteptau indeplinirea conditiei
! Apelurile notify()
si notifyAll()
nu elibereaza lock-ul, deci un thread nu va fi trezit imediat ci doar cand apeluri de mai sus au terminat de folosit lock-ul si l-au eliberat.
acquire()
si incrementat de apelul release()
.Contorul nu poate ajunge la valori negative deci atunci cand este apelata functia acquire()
si contorul este 0
thredul se blocheaza pana cand alt thread apeleaza release()
. Atunci cand este creat un semafor contorul are valoarea 1.
Exemplu: Problema producator-consumator, cand 3 producatori, 1 consumator si buffer nelimitat.
import time
import random
from threading import Thread
import threading
sem1 = threading.Semaphore(value=3) # 3 prod
# cons nu are semafor
class Prod(Thread):
def __init__(self,buf,n):
Thread.__init__(self)
self.idt = n
self.buf = buf
def run(self):
while True:
global sem1
sem1.acquire()
self.buf.append(1)
print "Prod",self.idt, " produce; Buffer=", self.buf
time.sleep(random.random()*5)
sem1.release()
class Cons(Thread):
def __init__(self,buf,idt):
Thread.__init__(self)
self.idt = idt
self.buf = buf
def run(self):
while True:
if len(self.buf) > 0:
del self.buf[0]
print "Cons",self.idt, " consuma; Buffer=", self.buf
time.sleep(random.random()*5)
def test():
buf = []
p1 = Prod(buf,0)
p2 = Prod(buf,1)
p3 = Prod(buf,2)
c = Cons(buf,0)
p1.start()
p2.start()
p3.start()
c.start()
test()
Niciun comentariu:
Trimiteți un comentariu