Presentation is loading. Please wait.

Presentation is loading. Please wait.

Multithreaded Programming in Python Nick Anastasia.

Similar presentations


Presentation on theme: "Multithreaded Programming in Python Nick Anastasia."— Presentation transcript:

1 Multithreaded Programming in Python Nick Anastasia

2 Background Basics: Process - a program in execution. Has its own address space, memory, stack, etc. All managed by the Operating System Thread - a "lightweight process" that can share a process with other threads and use the same context.

3 Python and Threading: Python execution is controlled by the Python Virtual Machine, the main loop of the interpreter Only ONE thread can execute in the interpreter at a time (implications on multiprocessor systems?) Access controlled by the Global Interpreter Lock GIL just like cpu scheduler New thread when running thread voluntarily sleeps, ends or when a specified number of instructions executes External code locks GIL because interpreter has no way of counting python byte code intervals on it (because its not python)

4 Life Without Threads: from time import sleep, ctime def loop0(): print 'start loop 0 at time: ', ctime() sleep(4) print 'done loop 0 at time: ', ctime() def loop1(): print 'start loop 1 at time; ', ctime() sleep(2) print 'done loop 1 at time: ', ctime() if __name__=='__main__': print 'starting program at time: ', ctime() loop0() loop1() print 'done program at time: ', ctime() Code example from book assume loop0 and loop1 actually do something useful and together they come up with a solution running them in parallel would be better.

5 thread Module: low level thread control, don't use it unless you really know what your doing ends program when main thread ends does not wait for child threads threading module is the way to go

6 Multithreaded solution: import thread from time import sleep, ctime def loop0(): print 'start loop 0 at time: ', ctime() sleep(4) print 'done loop 0 at time: ', ctime() def loop1(): print 'start loop 1 at time; ', ctime() sleep(2) print 'done loop 1 at time: ', ctime() if __name__=='__main__': print 'starting program at time: ', ctime() thread.start_new_thread(loop0,()) thread.start_new_thread(loop1,()) sleep(6) print 'done program at time: ', ctime() If main thread did not sleep longer than the child threads execution would terminate when the main function finishes.

7 thread Functions: thread.start_new_thread(function,args,kwards=None) Spawns a new thread and executes function with the given args and optional kwargs thread.allocate_lock() Allocates a LockType object thread.exit() exits the thread LockType Functions: aquire(wait=None) Attempts to aquire lock locked() returns true if lock aquired, false otherwise release() releases lock

8 Using Locks instead of Sleep: import thread from time import sleep, ctime loops = [4,2] def loop(nloop, nsec, lock): print 'start loop ',nloop,' at time: ', ctime() sleep(nsec) print 'done loop ',nloop,' at time: ', ctime() lock.release() if __name__=='__main__': print 'starting program at time: ', ctime() locks = [] nloops = range(len(loops)) for l in nloops: lock = thread.allocate_lock() lock.acquire() locks.append(lock) for l in nloops: thread.start_new_thread(loop,(l, loops[l], locks[l])) for l in nloops: while locks[l].locked(): pass print 'done program at time: ', ctime() 1. acquire a lock for each thread 2. execute each thread and then release its lock 3. wait for all locks to be released then finish program

9 Threading module objects: Thread Lock –Lock() RLock –RLock() Condition –Condition() Event –Event() Semaphore –Semaphore([value]) Timer –Timer(time,function) Object that represents a single thread of execution Primitive lock object LockType from thread Re-entrant lock object allows for a single thread to (re)acquire an already held lock Object that causes one thread to wait until a certain “condition” has been satisfied by another thread General version of condition variables can awaken any number of threads when the event happens Provides a “waiting area” for threads waiting for a lock Similar to Thread but waits an allotted period of time before running

10 Thread object Functions: start() run() join(timeout = None) getName() setName(name) isAlive() isDaemon() setdaemon(daemonic) Sets the daemon flag of the thread Thread functionality, usually overwritten (same as java threads) Beings thread execution Suspends main program until started threads terminate, blocks unless timeout is given Gets thread name Sets thread name Flag indicating whether thread is still running Returns the daemon flag of the thread

11 Lock, RLock, Condition, Semaphore, Event, and Timer Lock Functions: –acquire() –release() RLock Funcitons: –acquire() –release() Condition Functions: –acquire() –release() –wait() –notify() –notifyAll() Semaphore Functions: –acquire() –release() Event Funcitons: –isSet() –set() –clear() –wait() Timer: –Timer(time,function) –Thread Functions –cancel()

12 threading solution: import threading from time import sleep, ctime loops = [4,2] def loop(nloop, nsec): print 'start loop ',nloop,' at time: ', ctime() sleep(nsec) print 'done loop ',nloop,' at time: ', ctime() if __name__=='__main__': print 'starting program at time: ', ctime() threads = [] nloops = range(len(loops)) for l in nloops: t = threading.Thread(target=loop, args=(l,loops[l])) threads.append(t) for l in nloops: threads[l].start() for l in nloops: threads[l].join() print 'done program at time: ', ctime() 1. Make Thread objects from the loop function 2. Start Threads 3. Complete loops 4. Wait for Thread completion and finish program

13 Practical Solution: Making a function into a thread is nice for examples but more likely you’ll want more functionality Get it by extending the Thread class and overriding the run() function, very similar to JAVA threads

14 import threading from time import sleep, ctime loops = (4,2) class MyThread(threading.Thread): def __init__(self, func, args, name=''): threading.Thread.__init__(self) self.name=name self.func=func self.args=args def run(self): apply(self.func, self.args) def loop(nloop, nsec): print 'start loop ',nloop,' at time: ', ctime() sleep(nsec) print 'done loop ',nloop,' at time: ', ctime() if __name__=='__main__': print 'starting program at time: ', ctime() threads = [] nloops = range(len(loops)) for l in nloops: t = MyThread(loop, (l,loops[l]),loop.__name__) threads.append(t) for l in nloops: threads[l].start() for l in nloops: threads[l].join() print 'done program at time: ', ctime() 1. Make MyThread objects from the loop function 2. Start Threads 3. MyThread object creates thread and runs the function it is passed 4. Wait for Thread completion and finish program MyThread Object:

15 Other threading Functions: activeCount() number of currently active Thread objects currentThread() returns the current Thread object enumerate() returns a list of active Threads More on page 810

16 Application: Producer Consumer Problem Producer creates goods and places them in a Queue at random intervals Consumer consumes the produced goods from the Queue Queue used for inter-thread communication

17 MyThread Class: import threading from time import sleep, ctime class MyThread(threading.Thread): def __init__(self, func, args, name=''): threading.Thread.__init__(self) self.name=name self.func=func self.args=args def getResult(self): return self.res def run(self): print 'start ',self.name,' at time: ', ctime() self.res = apply(self.func, self.args) print 'finishing ',self.name,' at time: ', ctime()

18 prodcon.py from MyThread import MyThread from time import ctime, sleep from Queue import Queue from random import randint def writeQ(queue): print 'producing object for Q...',\ queue.put('xxx',1) print "size now", queue.qsize() def readQ(queue): val= queue.get(1) print 'consumed object from Q... \ size now', queue.qsize() def writer(queue, loops): for i in range(loops): writeQ(queue) sleep(randint(1,3)) def reader(queue, loops): for i in range(loops): readQ(queue) sleep(randint(2,5)) funcs = [writer,reader] nfuncs = range(len(funcs)) if __name__=='__main__': nloops=randint(2,5) q=Queue(32) threads=[] for i in nfuncs: t=MyThread(funcs[i],(q,nloops),funcs[i].\ __name__) threads.append(t) for i in nfuncs: threads[i].start() for i in nfuncs: threads[i].join() print 'all DONE'

19 mutex Module Provides the Mutex object A lock and queue of functions waiting to obtain the lock Functions: –test()check if locked –testandset() aquire lock if unlocked return true, false otherwise –lock(function, argument) put function and argument in the queue to be executed when the lock is available –unlock()unlock if the queue is empty, execute the next item in the queue if it is not empty

20 Questions?


Download ppt "Multithreaded Programming in Python Nick Anastasia."

Similar presentations


Ads by Google