我们使用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() # 得到一个锁,锁定 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()。
时间: 2024-11-18 20:29:01