(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)) /生产者消费者模式的更多相关文章

  1. 从头认识java-17.5 堵塞队列(以生产者消费者模式为例)

    这一章节我们来讨论一下堵塞队列.我们以下将通过生产者消费者模式来介绍堵塞队列. 1.什么是堵塞队列?(摘自于并发编程网对http://tutorials.jenkov.com/java-concurr ...

  2. python 锁 信号量 事件 队列

    什么是python 进程锁? #同步效率低,但是保证了数据安全  重点 很多时候,我们需要在多个进程中同时写一个文件,如果不加锁机制,就会导致写文件错乱 这个时候,我们可以使用multiprocess ...

  3. python 并发编程 多线程 信号量

    一 信号量 信号量也是一把锁,可以指定信号量为5,对比互斥锁同一时间只能有一个任务抢到锁去执行,信号量同一时间可以有5个任务拿到锁去执行 如果说互斥锁是合租房屋的人去抢一个厕所,那么信号量就相当于一群 ...

  4. Python 精进版SVIP版通过队列实现一个生产者消费者模型

    import time from multiprocessing import Process,Queue,JoinableQueue #生产者 def producer(q): for i in r ...

  5. python 并发编程 多线程 目录

    线程理论 python 并发编程 多线程 开启线程的两种方式 python 并发编程 多线程与多进程的区别 python 并发编程 多线程 Thread对象的其他属性或方法 python 并发编程 多 ...

  6. Java并发(基础知识)—— 阻塞队列和生产者消费者模式

    1.阻塞队列                                                                                        Blocki ...

  7. LabVIEW之生产者/消费者模式--队列操作 彭会锋

    LabVIEW之生产者/消费者模式--队列操作 彭会锋 本文章主要是对学习LabVIEW之生产者/消费者模式的学习笔记,其中涉及到同步控制技术-队列.事件.状态机.生产者-消费者模式,这几种技术在在本 ...

  8. 10 阻塞队列 & 生产者-消费者模式

    原文:http://www.cnblogs.com/dolphin0520/p/3932906.html 在前面我们接触的队列都是非阻塞队列,比如PriorityQueue.LinkedList(Li ...

  9. LabVIEW之生产者/消费者模式--队列操作

    LabVIEW之生产者/消费者模式--队列操作 彭会锋 本文章主要是对学习LabVIEW之生产者/消费者模式的学习笔记,其中涉及到同步控制技术-队列.事件.状态机.生产者-消费者模式,这几种技术在在本 ...

随机推荐

  1. Excel与Google Sheets中实现线性规划求解

    很久没更新过APS系列文章了,这段时间项目工作确实非常紧,所以只能抽点时间学习一下运筹学的入门知识,算是为以后的APS项目积累点基础.看了一些运筹学的书(都是科普级别的)发现原来我目前面对的很多排产. ...

  2. 使用uiautomator2进行webview页面的测试

    1.开发开启webview debug模式 2.使用VirtualXposed框架进行webview测试,详细见https://testerhome.com/topics/16156 下载,安装Vir ...

  3. 对话框--pop&dialog总结

    pinguo-zhouwei/CustomPopwindow:(通用PopupWindow,几行代码搞定PopupWindow弹窗(续)): 1,通用PopupWindow,几行代码搞定PopupWi ...

  4. FuzzScanner 信息收集小工具

    前言: 该工具集成了各种大牛的工具,比如子域名发现,目录扫描,nmap端口扫描,c段地址查询,端口指纹,以及waf查询 00X1: 安装不推荐git安装,首先直接githup脱下来:git clone ...

  5. Java读取Excel并与SqlServer库中的数据比较

    先说说需求.在SQL server数据库中的表里存在一些数据,现在整理的Excel文档中也存在一些数据,现在需要通过根据比较某个字段值(唯一)来判断出,在库中有但excel中没有的数据. 大概的思路就 ...

  6. idea spring boot docker 多项目 maven 编译

    1,重复的model [INFO] Scanning for projects... [ERROR] [ERROR] Some problems were encountered while proc ...

  7. Linux基础之常用命令整理(一)

    Linux 操作系统的安装 如今比较流线的linux操作系统 Centos Redhat  Fedora Ubuntu, 安装操作系统的提前是要有操作系统的镜像文件(.iso文件)并且必须为系统指定一 ...

  8. 【转录组入门】6:reads计数

    作业要求: 实现这个功能的软件也很多,还是烦请大家先自己搜索几个教程,入门请统一用htseq-count,对每个样本都会输出一个表达量文件. 需要用脚本合并所有的样本为表达矩阵.参考:生信编程直播第四 ...

  9. Source Insight 4.0安装后首次打开报错Unable to open or create

    错误提示大概如下: Unable to open or create ....我的文档/source insght4.0/xxx.sidb. 这个错误提示就是找不到这个文件,原因是应为有中文路径,那么 ...

  10. 阿里云centos7.4下tomcat8.5配置ssl证书

    环境 阿里云centos7.4 域名也是阿里申请的 jdk1.8 tomcat8.5 1.申请证书 登录到阿里云的域名管理,可以看到已经申请过得域名,我这里第一个已经配置了ssl,第二个未配置,点击更 ...