锁机制,信号机制,事件机制
一.锁机制
程序加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全
multiprocessing模块提供基于消息的ipc通信机制:队列和管道
l = Lock()
l.acquire() 锁,别的程序无法操作
l.release()开锁,允许别的进程操作
模拟抢票
#文件db的内容为:{"count":1} #注意一定要用双引号,不然json无法识别 #并发运行,效率高,但竞争写同一文件,数据写入错乱 from multiprocessing import Process,Lock import time,json,random def search(): dic=json.load(open('db')) print('\033[43m剩余票数%s\033[0m' %dic['count']) def get(): dic=json.load(open('db')) time.sleep(0.1) #模拟读数据的网络延迟 if dic['count'] >0: dic['count']-=1 time.sleep(0.2) #模拟写数据的网络延迟 json.dump(dic,open('db','w')) print('\033[43m购票成功\033[0m') def task(): search() get() if __name__ == '__main__': for i in range(100): #模拟并发100个客户端抢票 p=Process(target=task) p.start() 多进程同时抢购余票
#文件db的内容为:{"count":5} #注意一定要用双引号,不然json无法识别 #并发运行,效率高,但竞争写同一文件,数据写入错乱 from multiprocessing import Process,Lock import time,json,random def search(): dic=json.load(open('db')) print('\033[43m剩余票数%s\033[0m' %dic['count']) def get(): dic=json.load(open('db')) time.sleep(random.random()) #模拟读数据的网络延迟 if dic['count'] >0: dic['count']-=1 time.sleep(random.random()) #模拟写数据的网络延迟 json.dump(dic,open('db','w')) print('\033[32m购票成功\033[0m') else: print('\033[31m购票失败\033[0m') def task(lock): search() lock.acquire() get() lock.release() if __name__ == '__main__': lock = Lock() for i in range(100): #模拟并发100个客户端抢票 p=Process(target=task,args=(lock,)) p.start() 使用锁来保证数据安全
二.信号量
sem = Semphore(3) 3表示可以有3个进程同时进行操作数据,而后面的进程必须等待前面的进程结束才可以进行
例
from multiprocessing import Process,Semaphore import time,random def go_ktv(sem,user): sem.acquire() print('%s 占到一间ktv小屋' %user) time.sleep(random.randint(0,3)) #模拟每个人在ktv中待的时间不同 sem.release() if __name__ == '__main__': sem=Semaphore(4) p_l=[] for i in range(13): p=Process(target=go_ktv,args=(sem,'user%s' %i,)) p.start() p_l.append(p) for i in p_l: i.join() print('============》') 例子
三.事件
e = Event
四个方法 : e.set() 修改e.is_set为True e.clear修改e.is_set为False e.wait() 判断e.is_set是True还是
False,True继续执行 False就会停止
python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set wait clear
事件处理的机制:全局定义了一个'Flag',如果'Flag'值为 False,那么当程序执行event.wait 方法时就会阻塞,如果'Flag'值为True,那么event.wait方法时便不再阻塞
clear:将'Flag'设置为False
set:将'Flag'设置为True
from multiprocessing import Process, Event import time, random def car(e, n): while True: if not e.is_set(): # 进程刚开启,is_set()的值是Flase,模拟信号灯为红色 print('\033[31m红灯亮\033[0m,car%s等着' % n) e.wait() # 阻塞,等待is_set()的值变成True,模拟信号灯为绿色 print('\033[32m车%s 看见绿灯亮了\033[0m' % n) time.sleep(random.randint(3, 6)) if not e.is_set(): #如果is_set()的值是Flase,也就是红灯,仍然回到while语句开始 continue print('车开远了,car', n) break def police_car(e, n): while True: if not e.is_set():# 进程刚开启,is_set()的值是Flase,模拟信号灯为红色 print('\033[31m红灯亮\033[0m,car%s等着' % n) e.wait(0.1) # 阻塞,等待设置等待时间,等待0.1s之后没有等到绿灯就闯红灯走了 if not e.is_set(): print('\033[33m红灯,警车先走\033[0m,car %s' % n) else: print('\033[33;46m绿灯,警车走\033[0m,car %s' % n) break def traffic_lights(e, inverval): while True: time.sleep(inverval) if e.is_set(): print('######', e.is_set()) e.clear() # ---->将is_set()的值设置为False else: e.set() # ---->将is_set()的值设置为True print('***********',e.is_set()) if __name__ == '__main__': e = Event() for i in range(10): p=Process(target=car,args=(e,i,)) # 创建是个进程控制10辆车 p.start() for i in range(5): p = Process(target=police_car, args=(e, i,)) # 创建5个进程控制5辆警车 p.start() t = Process(target=traffic_lights, args=(e, 10)) # 创建一个进程控制红绿灯 t.start() print('============》') 红绿灯实例