In questa lezione abbiamo visto come l'uso dei thread porti ad aver bisogno di accedere ai dati in modo esclusivo e di sincronizzare i thread. Per questo, abbiamo introdotto eventi, lock e condition variables.
Inoltre, abbiamo introdotto i concetti di pila, coda e lista che approfondiremo nelle prossime lezioni.
Trovate in fondo alla pagina i due esempi di codice visti a lezione.
In this lecture we have shown how threading leads to a need for mutual exclusion in data accesses and thread synchronization. To this end, we have introduced events, locks and condition variables.
Producer and Consumers
#!/usr/bin/python
from threading import Thread, Lock, currentThread, enumerate, Event, Condition,
activeCount
from random import randint, choice
outputLock = Lock()
endThreads = Event()
class Buffer :
def __init__(self):
self.data = []
self.lock= Condition()
def enqueue(self,datum):
self.lock.acquire()
self.data.append(datum)
self.lock.notify()
self.lock.release()
def dequeue(self):
self.lock.acquire()
if not len(self.data) : self.lock.wait()
datum=self.data.pop()
self.lock.release()
return datum
def notify_end(self):
self.lock.acquire()
self.lock.notifyAll()
self.lock.release()
def __len__(self):
return len(self.data)
class BufferUser(Thread):
def __init__(self, buffer):
Thread.__init__(self)
self.buffer=buffer
class Consumer(BufferUser):
def run(self):
while not endThreads.isSet() :
datum = self.buffer.dequeue()
outputLock.acquire()
print currentThread(), datum
outputLock.release()
print 'Ending', currentThread()
class Producer(BufferUser):
def run(self):
while not endThreads.isSet() :
datum = currentThread(), randint(1,100)
self.buffer.enqueue(datum)
print 'Ending', currentThread()
buffers = [ Buffer() for i in range(3) ]
class Manager(Thread):
def run(self):
raw_input("Stop the system...")
outputLock.acquire()
threads = enumerate()
print 'Active Threads:', threads
endThreads.set()
for b in buffers :
b.notify_end()
outputLock.release()
for t in range(3):
Producer(choice(buffers)).start()
Consumer(choice(buffers)).start()
Manager().start()
for t in enumerate() :
if t!=currentThread():
t.join()
print 'All threads killed!'
print 'Buffers entry remaining:',
for b in buffers :
print len(b),
print ''
Barber's Problem
#!/usr/bin/python
from threading import Thread, Lock, currentThread, enumerate, Event, Condition, activeCount
from random import randint, choice
from time import sleep
endThreads = Event()
class BarberShop :
def __init__(self,nchairs):
self.nchairs = nchairs
self.busychairs = []
self.lock = Condition()
def sit(self):
self.lock.acquire()
if len(self.busychairs)>=self.nchairs : self.lock.wait()
event = Event()
self.busychairs.append(event)
self.lock.release()
event.wait()
def cut(self):
self.lock.acquire()
event = self.busychairs.pop()
self.lock.notify()
self.lock.release()
sleep(randint(0,3))
event.set()
def notify_end(self):
self.lock.acquire()
self.lock.notifyAll()
self.lock.release()
def busy(self):
return len(self.busychairs)>0
class BarberShopUser(Thread):
def __init__(self, shop):
Thread.__init__(self)
self.shop=shop
class Barber(BarberShopUser):
def run(self):
while not endThreads.isSet() :
if self.shop.busy() :
print 'Barber', currentThread(), 'working!'
self.shop.cut()
else :
print 'Barber', currentThread(), 'sleeping!'
sleep(randint(0,3))
print 'Ending', currentThread()
class Customer(BarberShopUser):
def run(self):
print 'Customer', currentThread(), 'entering barber shop!'
self.shop.sit()
print 'Customer', currentThread(), 'served!'
barbershop=BarberShop(4)
class Manager(Thread):
def run(self):
raw_input("Stop the system...")
threads = enumerate()
print 'Active Threads:', threads
endThreads.set()
barbershop.notify_end()
for t in range(2):
Barber(barbershop).start()
Manager().start()
for t in range(15):
sleep(randint(0,2))
Customer(barbershop).start()
for t in enumerate() :
if t!=currentThread():
t.join()
print 'All threads killed!'