锁,信号量 ,事件 Event模块
Posted 123zzy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了锁,信号量 ,事件 Event模块相关的知识,希望对你有一定的参考价值。
1. 锁
Lock模块: 保证一段代码,在同一时刻只能被一个进程执行.
lock = Lock() 创造了一把锁
acquire() 获取锁的钥匙
release() 归还这把锁的钥匙
ps: 多进程的数据的不安全性: 当多个进程共享一段数据的时候, 数据会出现不安全的现象, 需要加锁, 来维护数据的安全性.
例:
抢票:
抢票分析: 客户可以同一时间访问服务器,并且访问到 同一个余票数 当客户发出购买请求, 服务器必须进行同步处理, 一个一个来. from multiprocessing import Process,Lock import time def check(i): with open(‘余票‘) as f: con = f.read() print(‘第%s个人查到余票还剩%s张‘%(i,con)) def buy_ticket(i,l): l.acquire()# 拿钥匙,锁门 with open(‘余票‘) as f: con = int(f.read()) time.sleep(0.1) if con > 0: print(‘ 33[31m 第%s个人买到票了 33[0m‘%i) con -= 1 else: print(‘ 33[32m 第%s个人没有买到票 33[0m‘%i) time.sleep(0.1)# 是指 买完票后,把余票数量重写写入数据库的时间延迟 with open(‘余票‘,‘w‘) as f: f.write(str(con)) l.release()# 还钥匙,开门 if __name__ == ‘__main__‘: l = Lock() for i in range(10): p_ch = Process(target=check,args=(i+1,)) p_ch.start() for i in range(10): p_buy = Process(target=buy_ticket,args=(i+1,l)) p_buy.start()
银行同时取钱.存钱:
from multiprocessing import Process,Value,Lock import time def get_money(num,l):# 取钱 l.acquire()# 拿走钥匙,锁上门,不允许其他人进屋 for i in range(100): num.value -= 1 print(num.value) time.sleep(0.01) l.release()# 还钥匙,打开门,允许其他人进屋 def put_money(num,l):# 存钱 l.acquire() for i in range(100): num.value += 1 print(num.value) time.sleep(0.01) l.release() if __name__ == ‘__main__‘: num = Value(‘i‘,100) l = Lock() p = Process(target=get_money,args=(num,l)) p.start() p1 = Process(target=put_money, args=(num,l)) p1.start() p.join() p1.join() print(num.value)
2, 信号量
Semaphore模块: 多把钥匙 对应一把锁
本质就是: lock+count 计数 来实现的
sem = Semaphore(n)
n : 是指初始化一把锁配几把钥匙,一个int型
拿钥匙,锁门 l.acquire()
还钥匙,开门 l.release()
信号量机制比锁机制多了一个计数器,这个计数器是用来记录当前剩余几把钥匙的。
当计数器为0时,表示没有钥匙了,此时acquire()处于阻塞。
对于计数器来说,每acquire一次,计数器内部就减1,release一次,计数器就加1
例:
发廊:
from multiprocessing import Process,Semaphore import time import random def func(i,sem): sem.acquire() print(‘ 33[31m 第%s个人进入小黑屋,拿了钥匙锁上门 33[0m‘ % i) time.sleep(random.randint(3,5)) print(‘ 33[32m 第%s个人出去小黑屋,还了钥匙打开门 33[0m‘ % i) sem.release() if __name__ == ‘__main__‘: sem=Semaphore(5)# 初始化了一把锁5把钥匙,也就是说允许5个人同时进入小黑屋 # 之后其他人必须等待,等有人从小黑屋出来,还了钥匙,才能允许后边的人进入 for i in range(20): p=Process(target=func,args=(i,sem,)) p.start()
3, 事件 Event模块:
标志:在 事件创立之初,标志默认为False
wait(timeout=None) 等待 有一个关键字参数 timeout(超时) 以秒为单位.
e = Event()
# e.set() #将is_set()设为True
# e.clear() # 将is_set()设为False
# e.wait() #判断is_set的bool值,如果bool为True,则非阻塞,bool值为False,则阻塞
# e.is_set() # 标识
# 事件是通过is_set()的bool值,去标识e.wait() 的阻塞状态
# 当is_set()的bool值为False时,e.wait()是阻塞状态
# 当is_set()的bool值为True时,e.wait()是非阻塞状态
# 当使用set()时,是把is_set的bool变为True
# 当使用clear()时,是把is_set的bool变为False
例:
信号灯:
from multiprocessing import Process,Event import time import random def tra(e): ‘‘‘信号灯函数‘‘‘ # e.set() # print(‘ 33[32m 绿灯亮! 33[0m‘) while 1:# 红绿灯得一直亮着,要么是红灯要么是绿灯 if e.is_set():# True,代表绿灯亮,那么此时代表可以过车 time.sleep(5)# 所以在这让灯等5秒钟,这段时间让车过 print(‘ 33[31m 红灯亮! 33[0m‘)# 绿灯亮了5秒后应该提示到红灯亮 e.clear()# 把is_set设置为False else: time.sleep(5)# 此时代表红灯亮了,此时应该红灯亮5秒,在此等5秒 print(‘ 33[32m 绿灯亮! 33[0m‘)# 红的亮够5秒后,该绿灯亮了 e.set()# 将is_set设置为True def Car(i,e): e.wait()# 车等在红绿灯,此时要看是红灯还是绿灯,如果is_set为True就是绿灯,此时可以过车 print(‘第%s辆车过去了‘%i) if __name__ == ‘__main__‘: e = Event() triff_light = Process(target=tra,args=(e,))# 信号灯的进程 triff_light.start() for i in range(50):# 描述50辆车的进程 if i % 3 == 0: time.sleep(2) car = Process(target=Car,args=(i+1,e,)) car.start()
以上是关于锁,信号量 ,事件 Event模块的主要内容,如果未能解决你的问题,请参考以下文章
并发编程——GIL全局解释器锁死锁现象与递归锁信号量Event事件线程queue
Python入门学习-DAY36-GIL全局解释器锁死锁现象与递归锁信号量Event事件线程queue
并发编程---死锁||递归锁---信号量---Event事件---定时器