from
time
import
sleep, ctime
import
thread
loops = [
4
,
2
]
def
loop(nloop, nsec, lock):
print
'start loop'
, nloop,
'at:'
, ctime()
sleep(nsec)
print
'loop'
, nloop,
'done at:'
, ctime()
lock.release()
def
main():
print
'starting at:'
, ctime()
locks = []
nloops =
range
(
len
(loops))
for
i
in
nloops:
lock = thread.allocate_lock()
#锁列表
lock.acquire()
#获得锁
locks.append(lock)
for
i
in
nloops:
thread.start_new_thread(loop, (i, loops[i], locks[i]))
for
i
in
nloops:
while
locks[i].locked():
pass
print
'all done at:'
,ctime()
if
__name__ ==
'__main__'
:
main()
逐行解释:
1-6 行
在 Unix 启动信息行后面,我们导入了 thread 模块和 time 模块里我们早已熟悉的几个函数。我
们不再在函数里写死要等 4 秒和 2 秒,而是使用一个 loop()函数,把这些常量放在一个列表 loops
里。
8-12 行
loop()函数替换了我们之前的那几个 loop*()函数。在 loop()函数里,增加了一些锁的操作。
一个很明显的改变是,我们现在要在函数中记录下循环的号码和要睡眠的时间。最后一个不一样的
地方就是那个锁了。每个线程都会被分配一个事先已经获得的锁,在 sleep()的时间到了之后就释放
相应的锁以通知主线程,这个线程已经结束了。
14-34 行
主要的工作在包含三个循环的 main()函数中完成。我们先调用 thread.allocate_lock()函数创
建一个锁的列表,并分别调用各个锁的 acquire()函数获得锁。获得锁表示“把锁锁上”。锁上后,
我们就把锁放到锁列表 locks 中。下一个循环创建线程,每个线程都用各自的循环号,睡眠时间和
锁为参数去调用 loop()函数。为什么我们不在创建锁的循环里创建线程呢?有以下几个原因:(1) 我
们想到实现线程的同步,所以要让“所有的马同时冲出栅栏”。(2) 获取锁要花一些时间,如果你的
线程退出得“太快”,可能会导致还没有获得锁,线程就已经结束了的情况。
在线程结束的时候,线程要自己去做解锁操作。最后一个循环只是坐在那一直等(达到暂停主
线程的目的),直到两个锁都被解锁为止才继续运行。由于我们顺序检查每一个锁,所以我们可能会
要长时间地等待运行时间长且放在前面的线程,当这些线程的锁释放之后,后面的锁可能早就释放
了(表示对应的线程已经运行完了)。结果主线程只能毫不停歇地完成对后面这些锁的检查。最后两
行代码的意思你应该已经知道了,就是只有在我们直接运行这个脚本时,才运行 main()函数。