lock锁,Semaphore信号量,Event事件,进程队列Queue,生产者消费者模型,JoinableQueue---day31
1.lock锁
# ### 锁 lock
from multiprocessing import Process,Lock
import json,time
# (1) lock的基本语法
"""
上锁和解锁是一对,只上锁不解锁会发生死锁现象(程序发生阻塞,下面的代码不执行了)
互斥锁: 互斥锁是进程之间的互相排斥,谁抢到了资源谁就先使用,后抢到资源的后使用.
"""
"""
# 创建一把锁
lock = Lock()
# 上锁
lock.acquire()
# 执行操作
# 解锁
lock.release()
# lock.acquire() 死锁阻塞.
print("执行程序 .... ")
""" # (2) 模拟12306 抢票软件 # 读取票数,更新票数
def wr_info(sign,dic=None):
if sign == "r":
with open("ticket",mode="r",encoding="utf-8") as fp:
dic = json.load(fp)
return dic
elif sign == "w":
with open("ticket",mode="w",encoding="utf-8") as fp:
json.dump(dic,fp) # 抢票方法
def get_ticket(person):
# 获取数据库中实际数据
dic = wr_info("r") # 模拟网络延迟
time.sleep(0.5) if dic["count"] > 0:
print("%s抢到票了" % (person))
dic["count"] -= 1
# 更新数据库
wr_info("w",dic)
else:
print("%s没有抢到这张票" % (person)) def run(person,lock):
# 读取数据库中的实际票数
dic = wr_info("r")
print("%s 查询票数 : %s" % (person,dic["count"])) # 上锁
lock.acquire()
# 抢票
get_ticket(person)
# 解锁
lock.release() if __name__ == "__main__":
lock = Lock()
lst =["刘思敏7","云超1","张恒2","尉翼麟3","王振4","黎建忠5","刘鑫炜6","李天兆8","魏小林9","李博10"]
for i in lst:
p = Process(target=run,args=(i,lock))
p.start() """
# 总结: 区分同步和异步;
当创建10个进程的时候是异步的.直到查完票数截止;
当执行get_ticket这个方法时候,各个进程之间是同步的;
"""
2.Semaphore信号量
# ### 信号量 Semaphore 本质上就是锁,可以控制上锁的数量
"""
sem = Semaphore(4)
sem.acquire()
# 执行相应的操作
sem.release()
"""
from multiprocessing import Semaphore,Process
import time,random def ktv(person,sem):
sem.acquire()
# 开始唱歌
print("%s进入ktv,正在唱歌" % (person) )
time.sleep(random.randrange(3,7)) # 3 4 5 6
print("%s离开ktv,唱完了" % (person) )
sem.release() if __name__ == "__main__":
sem = Semaphore(4)
for i in range(10):
p = Process(target=ktv,args=("person%s" % (i) , sem))
p.start() """
# 总结:
Semaphore 可以设置上锁的数量
同一时间最多允许几个进程上锁;
创建进程的时候是异步的
在执行任务时候是同步的;
"""
3.Event事件
# ### 事件 (Event)
"""
# 阻塞事件 :
e = Event()生成事件对象e
e.wait()动态给程序加阻塞 ,
程序当中是否加阻塞完全取决于该对象中的is_set() [默认返回值是False]
# 如果是True 不加阻塞
# 如果是False 加阻塞 # 控制这个属性的值
# set()方法 将这个属性的值改成True
# clear()方法 将这个属性的值改成False
# is_set()方法 判断当前的属性是否为True (默认上来是False) Lock Semaphore Event 进程和进程之间的数据彼此隔离,但是可以通过socket互相发消息;
"""
# (1) 基本语法
from multiprocessing import Process,Event # 1
# e = Event()
# print(e.is_set())
# e.wait()
# print("程序运行中... ") # 2
"""
e = Event()
# 将阻塞事件中的值改成True
e.set()
print(e.is_set())
e.wait()
print("程序运行中1... ") # 将阻塞事件中的值改成False
e.clear()
e.wait()
print("程序运行中2... ")
"""
# 3
"""
e = Event()
# 参数: 最多等待时间是5秒,过了5秒之后阻塞放行
e.wait()
print("程序运行中3... ")
""" # (2) 模拟红绿灯效果
import time,random
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() # e = Event()
# traffic_light(e) 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(1,21):
time.sleep(random.randrange(0,2)) # 0 1
p2 = Process(target=car,args=(e,i))
p2.start()
"""
# (3) 改造红绿灯 (在跑完小车之后,把红绿灯给我炸了)
if __name__ == "__main__":
lst = []
e = Event()
p1 = Process(target=traffic_light,args=(e,))
# 把红绿灯变成守护进程
p1.daemon = True
p1.start() # 开始创建小车
for i in range(1,21):
time.sleep(random.randrange(0,2)) # 0 1
p2 = Process(target=car,args=(e,i))
p2.start()
lst.append(p2) # 让所有的小车都通过之后,在终止交通灯;
for i in lst:
i.join() print("程序结束 ... ")
4.进程队列Queue
# ### 进程队列
from multiprocessing import Process,Queue
"""先进先出,后进后出"""
import queue # 线程队列
# (1) 基本语法
"""
q = Queue()
# 1.put 往队列中存值
q.put(111)
q.put(222)
q.put(333)
# 2.get 从队列中取值
res = q.get()
print(res)
res = q.get()
print(res)
res = q.get()
print(res) # 3.队列里面没数据了,在调用get会发生阻塞
# res = q.get()
# print(res)
"""
# 4.get_nowait 存在兼容性问题(windows好用 linux不好用 不推荐使用)
"""
res = q.get_nowait()
print(res) # 队列问题
try:
res = q.get_nowait()
print(res)
except queue.Empty:
pass
""" # (2) 可以限定Queue队列的长度
"""
q1 = Queue(3)
q1.put(1)
q1.put(2)
q1.put(3)
# 超出了队列的长度,会发生阻塞
# q1.put(4)
# 如果列表满了,还往里面添加数据会直接报错.
q1.put_nowait(4)
""" # (3)进程之间通过队列交换数据
def func(q2):
# 2.子进程取数据
res = q2.get()
print(res)
# 3.子进程存数据
q2.put("刘思敏") if __name__ == "__main__":
q2 = Queue()
p = Process(target=func,args=(q2,))
p.start() # 1.主进程添加数据
q2.put("王振") # 为了等待子进程把数据塞到队列中,在获取,要加一个join
p.join() # 2.主进程获取数据
res = q2.get()
print("主程序执行结束:值为{}".format(res))
5.生产者消费者模型
# ### 生产者和消费者模型
"""
# 爬虫例子:
1号进程负责抓取页面中的内容放到队列里
2号进程负责把内容取出来,配合正则表达式,扣取关键字 1号进程可以理解成生产者
2号进程可以理解成消费者 相对理想的生产者和消费者模型:
追求彼此的速度相对均匀 从程序上来说:
生产者负责存储数据(put)
消费者负责获取数据(get)
""" # (1)基本模型
from multiprocessing import Process,Queue
import random,time # 消费者模型
def consumer(q,name):
while True:
food = q.get()
time.sleep(random.uniform(0.1,1))
print("%s 吃了一个%s" % (name,food)) # 生产者模型
def producer(q,name,food):
for i in range(5):
time.sleep(random.uniform(0.1,1))
print("%s 生产了 %s%s" % (name,food,i))
q.put(food+str(i)) if __name__ == "__main__":
q = Queue()
# 消费者1
p1 = Process(target=consumer,args=(q,"张恒"))
p1.start() # 生产者1
p2 = Process(target=producer,args=(q,"尉翼麟","黄金"))
p2.start() # (2)优化模型 # 消费者模型
def consumer(q,name):
while True:
food = q.get()
if food is None:
break
time.sleep(random.uniform(0.1,1))
print("%s 吃了一个%s" % (name,food)) # 生产者模型
def producer(q,name,food):
for i in range(5):
time.sleep(random.uniform(0.1,1))
print("%s 生产了 %s%s" % (name,food,i))
q.put(food+str(i)) if __name__ == "__main__":
q = Queue()
# 消费者1
p1 = Process(target=consumer,args=(q,"张恒"))
p1.start()
# 消费者2
a2 = Process(target=consumer,args=(q,"云超"))
a2.start() # 生产者1
p2 = Process(target=producer,args=(q,"尉翼麟","黄金"))
p2.start() # 生产者2
b2 = Process(target=producer,args=(q,"刘思敏","钻石"))
b2.start() # 在生产完所有的数据之后,在队列的末尾塞入一个None
p2.join()
b2.join()
# 消费者模型如果获取的是None,代表停止消费
q.put(None)
q.put(None)
6.JoinableQueue
# ### JoinableQueue
"""
put 存储
get 获取
task_done 队列计数减1
join 阻塞 task_done 配合 join 一起使用
[1,2,3,4,5]
队列计数5
put 一次 每存放一个值,队列计数器加1
get 一次 通过task_done让队列计数器减1
join 函数,会根据队列中的计数器来判定是阻塞还是放行
如果计数器变量是0,意味着放行,其他情况阻塞;
""" from multiprocessing import Process,JoinableQueue
# (1) 基本使用
"""
jq = JoinableQueue()
# put 会让队列计数器+1
jq.put("a")
print(jq.get())
# 通过task_done,让队列计数器-1
jq.task_done()
# 只有队列计数器是0的时,才会放行
jq.join() # 队列.join
print("finish")
""" # (2) 改造生产者消费者模型
import random,time # 消费者模型
def consumer(q,name):
while True:
food = q.get()
time.sleep(random.uniform(0.1,1))
print("%s 吃了一个%s" % (name,food))
q.task_done() # 生产者模型
def producer(q,name,food):
for i in range(5):
time.sleep(random.uniform(0.1,1))
print("%s 生产了 %s%s" % (name,food,i))
q.put(food+str(i)) if __name__ == "__main__":
q = JoinableQueue()
# 消费者1
p1 = Process(target=consumer,args=(q,"张恒"))
p1.daemon = True
p1.start() # 生产者1
p2 = Process(target=producer,args=(q,"尉翼麟","黄金"))
p2.start() # 把生产者所有的数据都装载到队列中
p2.join() # 当队列计数器减到0的时候,会立刻放行
# 必须等待消费者模型中所有的数据都task_done之后,变成0了就代表消费结束.
q.join() print("程序结束....")
lock锁,Semaphore信号量,Event事件,进程队列Queue,生产者消费者模型,JoinableQueue---day31的更多相关文章
- Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型
一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例 ...
- 互斥锁 线程理论 GIL全局解释器锁 死锁现象 信号量 event事件 进程池与线程池 协程实现并发
目录 互斥锁 multiprocessing Lock类 锁的种类 线程理论 进程和线程对比 开线程的两种方式(类似进程) 方式1 使用Thread()创建线程对象 方式2 重写Thread类run方 ...
- [并发编程 - socketserver模块实现并发、[进程查看父子进程pid、僵尸进程、孤儿进程、守护进程、互斥锁、队列、生产者消费者模型]
[并发编程 - socketserver模块实现并发.[进程查看父子进程pid.僵尸进程.孤儿进程.守护进程.互斥锁.队列.生产者消费者模型] socketserver模块实现并发 基于tcp的套接字 ...
- Day034--Python--锁, 信号量, 事件, 队列, 生产者消费者模型, joinableQueue
进程同步: 1. 锁 (重点) 锁通常被用来实现对共享资源的同步访问.为每一个共享资源创建一个Lock对象,当你需要访问该资源时,调用acquire方法来获取锁对象(如果其它线程已经获得了该锁, ...
- 进击的Python【第九章】:paramiko模块、线程与进程、各种线程锁、queue队列、生产者消费者模型
一.paramiko模块 他是什么东西? paramiko模块是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 先来个实例: import param ...
- python_way ,day11 线程,怎么写一个多线程?,队列,生产者消费者模型,线程锁,缓存(memcache,redis)
python11 1.多线程原理 2.怎么写一个多线程? 3.队列 4.生产者消费者模型 5.线程锁 6.缓存 memcache redis 多线程原理 def f1(arg) print(arg) ...
- 8.12 day31 进程间通信 Queue队列使用 生产者消费者模型 线程理论 创建及对象属性方法 线程互斥锁 守护线程
进程补充 进程通信 要想实现进程间通信,可以用管道或者队列 队列比管道更好用(队列自带管道和锁) 管道和队列的共同特点:数据只有一份,取完就没了 无法重复获取用一份数据 队列特点:先进先出 堆栈特点: ...
- python并发编程-进程间通信-Queue队列使用-生产者消费者模型-线程理论-创建及对象属性方法-线程互斥锁-守护线程-02
目录 进程补充 进程通信前言 Queue队列的基本使用 通过Queue队列实现进程间通信(IPC机制) 生产者消费者模型 以做包子买包子为例实现当包子卖完了停止消费行为 线程 什么是线程 为什么要有线 ...
- (并发编程)进程IPC,生产者消费者模型,守护进程补充
一.IPC(进程间通信)机制进程之间通信必须找到一种介质,该介质必须满足1.是所有进程共享的2.必须是内存空间附加:帮我们自动处理好锁的问题 a.from multiprocessing import ...
- 守护进程,进程安全,IPC进程间通讯,生产者消费者模型
1.守护进程(了解)2.进程安全(*****) 互斥锁 抢票案例3.IPC进程间通讯 manager queue(*****)4.生产者消费者模型 守护进程 指的也是一个进程,可以守护着另一个进程 一 ...
随机推荐
- [转帖]Python基础之判断和循环(三)
https://www.jianshu.com/p/5a7552821c63 一.判断 关于判断,跟字面意思一样,就是判断某一个时刻应不应该做某件事: 语法: if 判断条件: 执行语句-- else ...
- [转帖]Linux系统语言设置和locale命令详解
简介 Linux系统可以用locale命令查看语言设置,查看中英文环境,具体操作如下. 操作 1.查看当前安装有那些语言: [root@localhost /]# locale -a 2.当前语言相关 ...
- [转帖]天行健,国产CPU当自强不息
https://baijiahao.baidu.com/s?id=1699201892754975586 本页面的文字和图像允许在CC-BY-SA 3.0协议四和GNU自由文档许可证下修改和再使用 ...
- [转帖]Intel、海光、鲲鹏920、飞腾2500 CPU性能对比
https://plantegg.github.io/2021/06/18/%E5%87%A0%E6%AC%BECPU%E6%80%A7%E8%83%BD%E5%AF%B9%E6%AF%94/ Int ...
- 大数据平台Bug Bash大扫除最佳实践
一.背景 随着越来越多的"新人"在日常工作以及大促备战中担当大任,我们发现仅了解自身系统业务已不能满足日常系统开发运维需求.为此,大数据平台部门组织了一次Bug Bash活动,既能 ...
- 根据TxID获取上链数据
根据TxID获取上链信息 前段时间应甲方爸爸的要求,需要在现有的业务系统中新增一个根据TxID来查询上链信息的接口.搜了一圈发现相关的信息很少,最后只能祭出终极大招:Read Source Code. ...
- 13.2 外部DirectX绘制实现
在前一节中我们简单介绍了D3D绘制窗体所具备的基本要素,本节将继续探索外部绘制技术的实现细节,并以此实现一些简单的图形绘制功能,首先外部绘制的核心原理是通过动态创建一个新的窗口并设置该窗口属性为透明无 ...
- Linux基础命令 [补档-2023-06-28]
Linux基础命令 1-1.命令的基本格式 Linux系统命令的通用格式为: command [-options] [parameter] 其中 -command 命令本身 -op ...
- Spring自带的这11个工具类,真香!
前言 最近有些小伙伴,希望我分享一些好用的工具类,帮他们提升开发效率. 今天这篇文章专门跟大家一起总结一下,Spring框架本身自带的一些好用的工具类,希望对你会有所帮助. 1 Assert 很多时候 ...
- 文心一言 VS 讯飞星火 VS chatgpt (195)-- 算法导论14.3 3题
三.用go语言,请给出一个有效的算法,对一个给定的区间i,返回一个与i重叠且具有最小低端点的区间;或者当这样的区间不存在时返回T.nil. 文心一言,去掉math,代码正常运行: 在Go语言中,你可以 ...