9-2 事件,信号量,队列,锁

一 锁(Lock)json

当多个进程使用同一份数据资源的时候,就会引起数据安全或顺序混乱问题。就会用到锁安全

例如:买火车票,我如今只有一张票,10我的来买,若是不加锁,就会显示10我的都买到网络

 1 from multiprocessing import Process,Lock
 2 import time,json,random
 3 def search():#查票
 4     dic=json.load(open('db'))
 5     print('\033[31m剩余票数%s\033[0m' %dic['count'])
 6 
 7 def get(num):#买票
 8     dic=json.load(open('db'))
 9     time.sleep(random.random()) #模拟读数据的网络延迟
10     if dic['count'] >0:
11         dic['count']-=1
12         time.sleep(random.random()) #模拟写数据的网络延迟
13         json.dump(dic,open('db','w'))
14         print('\033[31m用户%s购票成功\033[0m'%num)
15 
16 def task(num,lock):
17     search()
18     lock.acquire()
19     get(num)
20     lock.release()
21 
22 if __name__ == '__main__':
23     lock = Lock()
24     for i in range(10): #模拟并发10个客户端抢票
25         p=Process(target=task,args = (i,lock))
26         p.start()

还有我开启三个进程让一一对应启动和结束一样也用到了锁并发

 1 import os
 2 import time
 3 import random
 4 from multiprocessing import Process,Lock
 5 
 6 def work(n,lock):
 7     lock.acquire()#取的钥匙
 8     print('%s:%s is running'%(n,os.getpid()))
 9     time.sleep(random.random())
10     print('%s:%s is done' %(n,os.getpid()))
11     lock.release()#释放
12 if __name__ == '__main__':
13     lock=Lock()
14     for i in range(3):
15         p=Process(target=work,args=(i,lock))
16         p.start()
17 
18 结果:
19 0:25068 is running
20 0:25068 is done
21 1:24296 is running
22 1:24296 is done
23 2:24092 is running
24 2:24092 is done

二 事件(Event)(用的不多)app

# 事件内部内置了一个标志
# wait 方法 若是这个标志是True,那么wait == pass
# wait 方法 若是这个标志是False,那么wait就会陷入阻塞,一直阻塞到标志从False变成True

# 一个事件在建立之初 内部的标志默认是False
# Flase -> True set()
# True -> False clear()
例子:红路灯模型
说明:
# 10个进程 模拟车 :车的行走要依靠当时的交通灯
# 交通灯是绿灯 车就走
# 交通灯是红灯 车就停 停到灯变绿
# wait 来等灯
# set clear 来控制灯
 1 from multiprocessing import Process, Event
 2 import time, random
 3 
 4 def car(e, n):
 5     while True:
 6         if not e.is_set():
 7             # 进程刚开启,is_set()的值是Flase,模拟信号灯为红色
 8             print('\033[31m红灯亮\033[0m,car%s等着' % n)
 9             e.wait()    # 阻塞,等待is_set()的值变成True,模拟信号灯为绿色
10             print('\033[32m车%s 看见绿灯亮了\033[0m' % n)
11             time.sleep(random.randint(3, 6))
12             if not e.is_set():   #若是is_set()的值是Flase,也就是红灯,仍然回到while语句开始
13                 continue
14             print('车开远了,car', n)
15             break
16 
17 def traffic_lights(e, inverval):
18     while True:
19         time.sleep(inverval)   # 先睡3秒
20         if e.is_set():         # 标志是True
21             print('######', e.is_set())
22             e.clear()  # ---->将is_set()的值设置为False
23         else:                 # 标志是False
24             e.set()    # ---->将is_set()的值设置为True
25             print('***********',e.is_set())
26 
27 
28 if __name__ == '__main__':
29     e = Event()   #e就是事件
30     t = Process(target=traffic_lights, args=(e, 3))  # 建立一个进程控制红绿灯
31     for i in range(10):
32         p=Process(target=car,args=(e,i,))  # 建立10个进程控制10辆车
33         p.start()
34     t.start()
35 
36     print('============》')

三 队列 (Queue)dom

q.get( [ block [ ,timeout ] ] ) 
返回q中的一个项目。若是q为空,此方法将阻塞,直到队列中有项目可用为止。block用于控制阻塞行为,默认为True. 若是设置为False,将引起Queue.Empty异常(定义在Queue模块中)。timeout是可选超时时间,用在阻塞模式中。若是在制定的时间间隔内没有项目变为可用,将引起Queue.Empty异常。

q.get_nowait( ) 
同q.get(False)方法。

q.put(item [, block [,timeout ] ] ) 
将item放入队列。若是队列已满,此方法将阻塞至有空间可用为止。block控制阻塞行为,默认为True。若是设置为False,将引起Queue.Empty异常(定义在Queue库模块中)。timeout指定在阻塞模式中等待可用空间的时间长短。超时后将引起Queue.Full异常。

 

建立共享的进程队列,Queue是多进程安全的队列,能够使用Queue实现多进程之间的数据传递。 ui

例子:spa

 1 from multiprocessing import Queue,Process
 2 
 3 def func(q,num):
 4     try:
 5         t = q.get_nowait() #拿一张票 不阻塞直接报错同q.get(False)
  6 print("%s抢到票了"%num)  7 except:pass  8  9 if __name__ == '__main__': 10 q = Queue() 11 q.put(1) #往里面放一张票 12 for i in range(10):#建立了10我的去抢一张票 13 Process(target=func,args=(q,i)).start() 14 15 16 #结果是只有一我的买到了票

 

四信号量  (Semaphore)了解便可,不多用线程

如:code

互斥锁同时只容许一个线程更改数据,而信号量Semaphore是同时容许必定数量的线程更改数据 。
假设商场里有4个迷你唱吧,因此同时能够进去4我的,若是来了第五我的就要在外面等待,等到有人出来才能再进去玩

 1 from multiprocessing import Process,Semaphore
 2 import time,random
 3 def go_ktv(sem,user):
 4     sem.acquire()
 5     print('%s占到一件ktv小屋' %user)
 6     time.sleep(random.randint(3,5))
 7     sem.release()
 8     print('%s走出小屋'%user)
 9 if __name__ == '__main__':
10     sem=Semaphore(4)
11     p_l=[]
12     for i in range(13):
13         p=Process(target=go_ktv,args=(sem,'user%s' %i,))
14         p.start()
15         p_l.append(p)
16     for i in p_l:
17         i.join()
18     print('##########')
相关文章
相关标签/搜索