互斥锁lock、信号量semaphore、事件Event、

时间:2023-03-09 20:47:11
互斥锁lock、信号量semaphore、事件Event、

1.互斥锁lock

应用在多进程中
互斥所lock:互斥锁是进程间的get_ticket互相排斥
进程之间,谁先枪占到资源,谁就先上锁,等到解锁之后,下一个进程在继续使用。
# 语法:
上锁: lock.acquire()
解锁: lock.release()

(1)基本语法

from multiprocessing import Process,Lock

lock = Lock()
# 上锁
lock.acquire()
print(1)
# lock.release() # 如果不解锁,2 就不会打印。
lock.acquire()
print(2)
lock.release()

(2)模拟抢票

from multiprocessing import Process
import json def wr_info(sign,dic=None):
if sign == "r":
with open("ticket.txt" ,mode="r",encoding="utf-8")as fp:
dic = json.load(fp)
return dic
elif sign == "w":
with open("ticket.txt",mode="w",encoding="utf-8")as fp:
json.dump(dic,fp) # 抢票的方法
def get_ticket(person):
# 读取数据库中的实际票数
dic = wr_info("r") time.sleep(0.1)
if dic["count"] > 0:
print("%s 抢票成功 !!"%(person))
dic["count"] -= 1
# 更新数据库
wr_info("w",dic)
else:
print("%s抢票失败"%(person))
# get_ticket("zhangsan")
# 用ticket来进行统一的函数调用
def ticket(person,lock):
# 查询票数
dic = wr_info("r")
print("%s查询票数是%s"%(person,dic["count"]))
# 遇到了acquire上锁之后,进程之间变成同步
lock.acquire()
# 开始签票
get_ticket(person)
lock.release() if __name__ == '__main__':
lock = Lock()
for i in range(5):
p = Process(target=ticket,args=("person%s"%(i),lock))
p.start()

(3)区分同步和异步

from multiprocessing import Process

def func(num,lock):
# 同步上锁
lock.acquire()
print(num)
lock.release()
if __name__ == "__main__":
lock = Lock()
for i in range(10):
# 异步并发
p = Process(target=func,args=(i,lock))
p.start()

2.信号量semaphore

  本质上就是锁,同一时间可以上多把锁

# 语法:
sem = Semaphore(3)
sem.acquire()
sem.release()

(1)基本用法

import time
import random
from multiprocessing import Process,Semaphore
def ktv(person,sem):
sem.acquire()
print("%s进入了ktv,正在唱歌"%(person))
time.sleep(random.randrange(3,6))
print("%s唱完了,离开了ktv"%(person))
sem.release() if __name__ == "__main__":
sem = Semaphore(3)
for i in range(10):
p = Process(target=ktv,args=("person%s"%(i),sem))
p.start()

注意:

lock 多个进程之间,一次只能上一把锁
Semaphore 多个进程之间,可以自定义上锁的数量,不限于一个

3.事件Event

# 阻塞事件
  e = Event()生成事件对象e
  e.wait()动态给程序加阻塞,程序当中是否加阻塞完全取决与该对象中的is_set()[默认返回值是False]
  # 如果是True,不加阻塞
  # 如果是False 加阻塞
#控制这个属性的值
  # set()方法 将这个属性的值改成True
  # clear()方法 将这个属性的值改成False
  # is_set()方法 判断当前的属性是否为True (默认上来是False)

(1)基本语法

from multiprocessing import Process,Event
e = Event() # 实例化,生成对象e
print(e.is_set()) # 查看对象e中的is_set()是True还是False。默认是False
e.wait() # 加阻塞。is_set()是False
print(1) # (2)
e = Event()
e.set() # 将is_set() 改成True
e.wait() # 不加阻塞
print(3) e.clear() # 把True=>False
e.wait()
print(444)

(2)红绿灯

import time,random
from multiprocessing import Process,Event
def traffic_light(e):
# 默认红灯亮
print("红灯亮")
while True:
if e.is_set():
# 让绿灯亮1秒钟
time.sleep(1)
#切换红灯亮
print("红灯亮")
# 把True改成False
e.clear()
else:
# 让红灯亮1秒钟
time.sleep(1)
# 切换成绿灯亮
print("绿灯亮")
# 把默认值从False改成True
e.set() def car(e,i):
# 判断如果是红灯亮,就执行下面代码
if not e.is_set():
print("car%s 在等待"% (i))
e.wait()
print("car%s通行了"%(i)) """
# 方法一
if __name__ == "__main__":
e = Event()
# 创建交通灯对象
p1 = Process(target=traffic_light,args=(e,))
p1.start() # 创建小车
for i in range(10):
time.sleep(random.randrange(0,2))
p2 = Process(target=car,args=(e,i))
p2.start() """ # 方法二: 优化红绿灯代码[当小车执行结束的时候,把红绿灯终止]
if __name__ == '__main__':
lst = []
e = Event()
# 创建交通灯对象
p1 = Process(target=traffic_light,args=(e,))
p1.daemon=True
p1.start() # 创建小车
for i in range(20):
time.sleep(random.randrange(0,2))
p2 = Process(target=car,args=(e,i))
p2.start() # 等所有小车通行之后,关闭守护程序
for i in lst:
i.join() print("主程序执行结束。。。")