python 并发编程 锁 / 信号量 / 事件 / 队列(进程间通信(IPC)) /生产者消费者模式
(1)锁:进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理。
虽然使用加锁的形式实现了顺序的执行,但是程序又重新变成串行了,这样确实会浪费了时间,却保证了数据的安全。 (Lock)
import json
from multiprocessing import Process,Lock ###### 锁 ######
import time
import random def get_ticket(i,ticket_lock):
print('我们到齐了')
time.sleep(1)
ticket_lock.acquire()
with open('text', 'r') as f:
last_ticket_info = json.load(f)
last_ticket = last_ticket_info['count']
if last_ticket > 0:
time.sleep(random.random())
last_ticket = last_ticket - 1
last_ticket_info['count'] = last_ticket
with open('text','w') as f:
json.dump(last_ticket_info,f)
print('%s号抢到了。'%i)
else:
print("%s号傻逼,没抢到"%i)
ticket_lock.release() if __name__ == '__main__':
ticket_lock = Lock()
for i in range(10):
p = Process(target=get_ticket,args=(i,ticket_lock,))
p.start() ##############
我们到齐了
我们到齐了
我们到齐了
我们到齐了
我们到齐了
我们到齐了
我们到齐了
我们到齐了
我们到齐了
我们到齐了
4号傻逼,没抢到
5号傻逼,没抢到
0号傻逼,没抢到
2号傻逼,没抢到
1号傻逼,没抢到
3号傻逼,没抢到
8号傻逼,没抢到
7号傻逼,没抢到
6号傻逼,没抢到
9号傻逼,没抢到
抢票示例
(2)信号量: (Semaphore)
from multiprocessing import Process,Semaphore ## 信号量 ##
import time def dabaojian(i,s):
s.acquire()
print('%s号来洗脚'%i)
time.sleep(1)
s.release() if __name__ == '__main__':
s = Semaphore(4)
for i in range(10):
p = Process(target=dabaojian,args=(i,s,))
p.start() #########
5号来洗脚
0号来洗脚
1号来洗脚
4号来洗脚 2号来洗脚
3号来洗脚
7号来洗脚
6号来洗脚 8号来洗脚
9号来洗脚 Process finished with exit code 0
洗脚示例
(3)事件: 事件完成红绿灯示例 (Event)
from multiprocessing import Process,Event #### 事件 ####
import time def taffic_lights(e):
while 1:
print('红灯亮')
time.sleep(5) e.set()
print('绿灯亮')
time.sleep(3)
e.clear() def car(i,e): if not e.is_set():
print('我们在等待。。。')
e.wait()
print('走你')
else:
print('可以走了。。') if __name__ =='__main__':
e = Event()
hld = Process(target=taffic_lights,args=(e,))
hld.start() while 1:
time.sleep(0.5) for i in range(3):
p = Process(target=car,args=(i,e,))
p.start() #################################
红灯亮
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
我们在等待。。。
绿灯亮
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
走你
可以走了。。
可以走了。。
可以走了。。
可以走了。。
可以走了。。
可以走了。。
可以走了。。
可以走了。。
可以走了。。
可以走了。。
可以走了。。
可以走了。。
可以走了。。
可以走了。。
可以走了。。
可以走了。。
可以走了。。
可以走了。。
红灯亮
事件模拟完成红绿灯示例
(4)队列:进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的。队列就像一个特殊的列表,但是可以设置固定长度,并且从前面插入数据,从后面取出数据,先进先出。
Queue([maxsize]) 创建共享的进程队列。
参数 :maxsize是队列中允许的最大项数。如果省略此参数,则无大小限制。
底层队列使用管道和锁实现。
queue的方法介绍:
q = Queue([maxsize])
创建共享的进程队列。maxsize是队列中允许的最大项数。如果省略此参数,则无大小限制。底层队列使用管道和锁定实现。另外,还需要运行支持线程以便队列中的数据传输到底层管道中。
Queue的实例q具有以下方法: 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异常。 q.qsize()
返回队列中目前项目的正确数量。此函数的结果并不可靠,因为在返回结果和在稍后程序中使用结果之间,队列中可能添加或删除了项目。在某些系统上,此方法可能引发NotImplementedError异常。 q.empty()
如果调用此方法时 q为空,返回True。如果其他进程或线程正在往队列中添加项目,结果是不可靠的。也就是说,在返回和使用结果之间,队列中可能已经加入新的项目。 q.full()
如果q已满,返回为True. 由于线程的存在,结果也可能是不可靠的(参考q.empty()方法)。。
代码示例:
from multiprocessing import Process,Queue ##### 队列 ##### q = Queue(3) q.put(1)
print(q.full())
q.put(2)
q.put(3)
print(q.full()) print(q.get())
print(q.empty())
print(q.get())
print(q.get())
print(q.empty())
print(q.get()) while 1:
try:
q.get(False)
# q.get_nowait()
except:
print('队列目前为空') ##########################
False
True
1
False
2
3
True
队列的简单示例
子进程和父进程通过队列进行通信
from multiprocessing import Process,Queue
import time def girl(q):
print('来自boy的信息',q.get())
print('来自领导的凝视',q.get()) def boy(q):
q.put('约么?') if __name__ == '__main__':
q = Queue(5)
boy_p = Process(target=boy,args=(q,))
girl_p = Process(target=girl,args=(q,))
boy_p.start()
girl_p.start()
time.sleep(1)
q.put('好好工作,别乱搞') ##########################
来自boy的信息 约么?
来自领导的凝视 好好工作,别乱搞
子进程与父进程通过队列进行通信
生产者消费者模式:
什么是生产者消费者模式:
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力,并且我可以根据生产速度和消费速度来均衡一下多少个生产者可以为多少个消费者提供足够的服务,就可以开多进程等等,而这些进程都是到阻塞队列或者说是缓冲区中去获取或者添加数据。
示例: 主进程在生产者生产完毕后发送结束信号None
from multiprocessing import Process,Queue
import time def shengchan(q):
for i in range(1,11):
time.sleep(1)
print('生产了%s号包子'%i)
q.put(i) def xiaofei(q):
while 1:
time.sleep(2)
s = q.get()
if s == None:
break
else:
print('消费者吃了%s包子'%s)
if __name__ =='__main__':
q = Queue(20)
sheng_p = Process(target=shengchan,args=(q,))
sheng_p.start()
xiao_p = Process(target=xiaofei,args=(q,))
xiao_p.start()
sheng_p.join() q.put(None) ############################
生产了包子1号
消费者吃了1包子
生产了包子2号
生产了包子3号
消费者吃了2包子
生产了包子4号
生产了包子5号
消费者吃了3包子
生产了包子6号
生产了包子7号
消费者吃了4包子
生产了包子8号
生产了包子9号
消费者吃了5包子
生产了包子10号
消费者吃了6包子
消费者吃了7包子
消费者吃了8包子
消费者吃了9包子
消费者吃了10包子 Process finished with exit code 0
JoinableQueue([maxsize])
#JoinableQueue([maxsize]):这就像是一个Queue对象,但队列允许项目的使用者通知生成者项目已经被成功处理。通知进程是使用共享的信号和条件变量来实现的。 #参数介绍:
maxsize是队列中允许最大项数,省略则无大小限制。
#方法介绍:
JoinableQueue的实例p除了与Queue对象相同的方法之外还具有:
q.task_done():使用者使用此方法发出信号,表示q.get()的返回项目已经被处理。如果调用此方法的次数大于从队列中删除项目的数量,将引发ValueError异常
q.join():生产者调用此方法进行阻塞,直到队列中所有的项目均被处理。阻塞将持续到队列中的每个项目均调用q.task_done()方法为止,也就是队列中的数据全部被get拿走了。
示例:JoinableQueue队列实现生产者消费者模型
import time
from multiprocessing import Process,Queue,JoinableQueue def producer(q):
for i in range(1,11):
time.sleep(0.5)
print('生产了包子%s号' % i)
q.put(i)
q.join()
print('在这里等你')
def consumer(q):
while 1:
time.sleep(1)
s = q.get()
print('消费者吃了%s包子' % s)
q.task_done() #给q对象发送一个任务结束的信号 if __name__ == '__main__':
#通过队列来模拟缓冲区,大小设置为20
q = JoinableQueue(20)
#生产者进程
pro_p = Process(target=producer,args=(q,))
pro_p.start()
#消费者进程
con_p = Process(target=consumer,args=(q,))
con_p.daemon = True #
con_p.start()
pro_p.join()
print('主进程结束') ##########################
生产了包子1号
生产了包子2号
消费者吃了1包子
生产了包子3号
生产了包子4号
消费者吃了2包子
生产了包子5号
生产了包子6号
消费者吃了3包子
生产了包子7号
消费者吃了4包子
生产了包子8号
生产了包子9号
消费者吃了5包子
生产了包子10号
消费者吃了6包子
消费者吃了7包子
消费者吃了8包子
消费者吃了9包子
消费者吃了10包子
在这里等你
主进程结束 Process finished with exit code 0
JoinableQueue队列实现生产者消费者模型
逻辑思维如下图:

python 并发编程 锁 / 信号量 / 事件 / 队列(进程间通信(IPC)) /生产者消费者模式的更多相关文章
- 从头认识java-17.5 堵塞队列(以生产者消费者模式为例)
这一章节我们来讨论一下堵塞队列.我们以下将通过生产者消费者模式来介绍堵塞队列. 1.什么是堵塞队列?(摘自于并发编程网对http://tutorials.jenkov.com/java-concurr ...
- python 锁 信号量 事件 队列
什么是python 进程锁? #同步效率低,但是保证了数据安全 重点 很多时候,我们需要在多个进程中同时写一个文件,如果不加锁机制,就会导致写文件错乱 这个时候,我们可以使用multiprocess ...
- python 并发编程 多线程 信号量
一 信号量 信号量也是一把锁,可以指定信号量为5,对比互斥锁同一时间只能有一个任务抢到锁去执行,信号量同一时间可以有5个任务拿到锁去执行 如果说互斥锁是合租房屋的人去抢一个厕所,那么信号量就相当于一群 ...
- Python 精进版SVIP版通过队列实现一个生产者消费者模型
import time from multiprocessing import Process,Queue,JoinableQueue #生产者 def producer(q): for i in r ...
- python 并发编程 多线程 目录
线程理论 python 并发编程 多线程 开启线程的两种方式 python 并发编程 多线程与多进程的区别 python 并发编程 多线程 Thread对象的其他属性或方法 python 并发编程 多 ...
- Java并发(基础知识)—— 阻塞队列和生产者消费者模式
1.阻塞队列 Blocki ...
- LabVIEW之生产者/消费者模式--队列操作 彭会锋
LabVIEW之生产者/消费者模式--队列操作 彭会锋 本文章主要是对学习LabVIEW之生产者/消费者模式的学习笔记,其中涉及到同步控制技术-队列.事件.状态机.生产者-消费者模式,这几种技术在在本 ...
- 10 阻塞队列 & 生产者-消费者模式
原文:http://www.cnblogs.com/dolphin0520/p/3932906.html 在前面我们接触的队列都是非阻塞队列,比如PriorityQueue.LinkedList(Li ...
- LabVIEW之生产者/消费者模式--队列操作
LabVIEW之生产者/消费者模式--队列操作 彭会锋 本文章主要是对学习LabVIEW之生产者/消费者模式的学习笔记,其中涉及到同步控制技术-队列.事件.状态机.生产者-消费者模式,这几种技术在在本 ...
随机推荐
- 工控随笔_13_西门子_WinCC的VBS脚本_04_变量类型之二
上一个随笔说了一些关于vbs变量类型的内容,这一篇我们继续说说变量类型相关的内容. 一.NULL补充内容 '需要注意的是,NULL不能简单通过 = 来进行比较,而必须通过 'IsNull函数来实现 ' ...
- primo驱动启动顺序
primo驱动启动顺序HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\ServiceGroupOrderSystem ReservedEMSWdfLoa ...
- Firefox控制台日志转入文件
应该说这个需求并不常见-但有时候我的确想过,要是能知道Firefox此时在干吗就好了–有那么几次,该运行的脚本没有运行,状态条显示页面的加载并未完成,但你却永远等不到它. 意外地是,谷哥和度娘似乎并不 ...
- centos7虚拟机克隆后设置固定IP
虚拟机centos7克隆一份出来之后,新centos7更改了固定IP,可是不生效.重启网卡时报错: network.service: control process exited, code=exit ...
- SfMLearner 记录
2019年3月2日09:29:54 正在看SfMLearner的pytorch源码,意识到无监督的深度估计最重要的是利用实体的一致性 来建立loss. 对于一个不移动的物体,相机从一个pose到另一个 ...
- HP880G3 安装RHEL6.5
###关于读不到网卡驱动的问题 HP 880G3 在安装系统的时候会提示acpi错误 需要按F9 选择 lency开头走U盘安装系统 进入安装界面按tab 输入 acpi=off 这样就可以安装了 ...
- Python 网站后台扫描脚本
Python 网站后台扫描脚本 #!/usr/bin/python #coding=utf-8 import sys import urllib import time url = "ht ...
- 使用plot_importance绘制特征重要性曲线
代码如下所示: # -*- coding: utf-8 -*- #导入需要的包 import matplotlib.pyplot as plt from sklearn import datasets ...
- Exp1 PC平台逆向破解 20164311
实验目标: 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 该程序同时包含另一个代码片段,getSh ...
- apache_php_mysql
软件下载 目前,Apache和PHP均未出现官方的64位版本. Apache 64位: http://www.blackdot.be/?inc=apache/binaries 这个安装文件我已经上传到 ...