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!'