飞哥ABC 阅读(104) 评论(0)

我们使用mutex(Python中的Lock类对象)来实现线程的同步:

lock.acquire() 相当于P操作,得到一个锁,
lock.release()相当于V操作,释放一个锁

 1 # -*- coding: cp936 -*-
 2 import threading  # Python主要通过标准库中的threading包来实现多线程
 3 import time
 4 import os
 5 
 6 
 7 def doChore():      #作为间隔  每次调用间隔0.5s
 8     time.sleep(0.5)
 9 
10 
11 def booth(tid):
12     global i
13     global lock
14     while True:
15         lock.acquire()                # Lock; or wait if other thread is holding the lock
16         if i != 0:
17             i = i - 1                 # 售票 售出一张减少一张
18             print(tid,':now left:',i) # 剩下的票数
19             doChore()                 
20         else:
21             print("Thread_id",tid," No more tickets")
22             os._exit(0)              # 票售完   退出程序
23         lock.release()               # 释放锁
24         doChore()                    
25 
26 # Start of the main function
27 i= 15                           # 初始化票数
28 lock = threading.Lock()              # 
29 
30 # 总共设置了10个线程
31 for k in range(10):
32     new_thread = threading.Thread(target=booth,args=(k,))   # 创建线程; Python使用threading.Thread对象来代表线程
33     new_thread.start()                                      # 调用start()方法启动线程

  • 我们在函数中使用global来声明变量为全局变量,从而让多线程共享i和lock (在C语言中,我们通过将变量放在所有函数外面来让它成为全局变量)。如果不这么声明,由于i和lock是不可变数据对象,它们将被当作一个局部变量。如果是可变数据对象的话,则不需要global声明。我们甚至可以将可变数据对象作为参数来传递给线程函数。这些线程将共享这些可变数据对象。

  • 在booth中使用了两个doChore()函数。可以在未来改进程序,以便让线程除了进行i=i-1之外,做更多的操作,比如打印剩余票数,找钱,或者喝口水之类的。第一个doChore()依然在Lock内部,所以可以安全地使用共享资源 (critical operations, 比如打印剩余票数)。第二个doChore()时,Lock已经被释放,所以不能再去使用共享资源。这时候可以做一些不使用共享资源的操作 (non-critical operation, 比如找钱、喝水)。我故意让doChore()等待了0.5秒,以代表这些额外的操作可能花费的时间。你可以定义的函数来代替doChore()。