15.04.2013 Views

Core Python Programming (2nd Edition)

Core Python Programming (2nd Edition)

Core Python Programming (2nd Edition)

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

We did not have any code that told the main thread to wait for the child threads to complete before<br />

continuing. This is what we mean by threads requiring some sort of synchronization. In our case, we<br />

used another sleep() call as our synchronization mechanism. We used a value of 6 seconds because we<br />

know that both threads (which take 4 and 2 seconds, as you know) should have completed by the time<br />

the main thread has counted to 6.<br />

You are probably thinking that there should be a better way of managing threads than creating that<br />

extra delay of 6 seconds in the main thread. Because of this delay, the overall runtime is no better than<br />

in our single-threaded version. Using sleep() for thread synchronization as we did is not reliable. What if<br />

our loops had independent and varying execution times? We may be exiting the main thread too early or<br />

too late. This is where locks come in.<br />

Making yet another update to our code to include locks as well as getting rid of separate loop functions,<br />

we get mtsleep2.py, presented in Example 18.3. Running it, we see that the output is similar to mtsleep1.<br />

py. The only difference is that we did not have to wait the extra time for mtsleep1.py to conclude. By<br />

using locks, we were able to exit as soon as both threads had completed execution.<br />

$ mtsleep2.py<br />

starting at: Sun Aug 13 16:34:41 2006<br />

start loop 0 at: Sun Aug 13 16:34:41 2006<br />

start loop 1 at: Sun Aug 13 16:34:41 2006<br />

loop 1 done at: Sun Aug 13 16:34:43 2006<br />

loop 0 done at: Sun Aug 13 16:34:45 2006<br />

all DONE at: Sun Aug 13 16:34:45 2006<br />

Example 18.3. Using tHRead and Locks (mtsleep2.py)<br />

Rather than using a call to sleep() to hold up the main thread as in mtsleep1.py, the use of<br />

locks makes more sense.<br />

1 #!/usr/bin/env python<br />

2<br />

3 import thread<br />

4 from time import sleep, ctime<br />

5<br />

6 loops = [4,2]<br />

7<br />

8 def loop(nloop, nsec, lock):<br />

9 print 'start loop', nloop, 'at:', ctime()<br />

10 sleep(nsec)<br />

11 print 'loop', nloop, 'done at:', ctime()<br />

12 lock.release()<br />

13<br />

14 def main():<br />

15 print 'starting at:', ctime()<br />

16 locks = []<br />

17 nloops = range(len(loops))<br />

18<br />

19 for i in nloops:<br />

20 lock = thread.allocate_lock()<br />

21 lock.acquire()<br />

22 locks.append(lock)<br />

23<br />

24 for i in nloops:

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!