[Python编程(第4版)].(Programming.Python.4th.Edition).Mark.Lutz.文字版

(yzsuai) #1

Example 5-8. PP4E\System\Threads\thread-count-wait1.py


"""
uses mutexes to know when threads are done in parent/main thread,
instead of time.sleep; lock stdout to avoid comingled prints;
"""


import _thread as thread
stdoutmutex = thread.allocate_lock()
exitmutexes = [thread.allocate_lock() for i in range(10)]


def counter(myId, count):
for i in range(count):
stdoutmutex.acquire()
print('[%s] => %s' % (myId, i))
stdoutmutex.release()
exitmutexes[myId].acquire() # signal main thread


for i in range(10):
thread.start_new_thread(counter, (i, 100))


for mutex in exitmutexes:
while not mutex.locked(): pass
print('Main thread exiting.')


A lock’s locked method can be used to check its state. To make this work, the main
thread makes one lock per child and tacks them onto a global exitmutexes list (re-
member, the threaded function shares global scope with the main thread). On exit,
each thread acquires its lock on the list, and the main thread simply watches for all
locks to be acquired. This is much more accurate than naïvely sleeping while child
threads run in hopes that all will have exited after the sleep. Run this on your own to
see its output—all 10 spawned threads count up to 100 (they run in arbitrarily inter-
leaved order that can vary per run and platform, but their prints run atomically and do
not comingle), before the main thread exits.


Depending on how your threads run, this could be even simpler: since threads share
global memory anyhow, we can usually achieve the same effect with a simple global
list of integers instead of locks. In Example 5-9, the module’s namespace (scope) is
shared by top-level code and the threaded function, as before. exitmutexes refers to the
same list object in the main thread and all threads it spawns. Because of that, changes
made in a thread are still noticed in the main thread without resorting to extra locks.


Example 5-9. PP4E\System\Threads\thread-count-wait2.py


"""
uses simple shared global data (not mutexes) to know when threads
are done in parent/main thread; threads share list but not its items,
assumes list won't move in memory once it has been created initially
"""


import _thread as thread
stdoutmutex = thread.allocate_lock()


196 | Chapter 5: Parallel System Tools

Free download pdf