(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. 虚拟机中的linux系统文件突然全部变成只读的问题

    当宿主系统和虚拟机的IO都比较繁忙时,虚拟机的IO请求得不到及时的响应.虚拟机Linux不知道自己运行在虚拟机里面,会认为是磁盘IO错误,为了保护磁盘数据会remount分区为只读. 这时候如果只是对 ...

  2. 在命令行终端运行 Elisp 脚本

    通常,我们在 Emacs 中运行 Elisp 代码片段,但是也可能需要在命令行终端运行 Elisp 脚本程序.在命令行终端运行 Elisp 脚本需要使用 --script 选项,例如: emacs - ...

  3. 微信小程序中的组件使用2

    需求    上面两个页面是同一个小程序的不同页面,两个页面中都是用到了label,有相似的地方,但是也有不同之处,这个时候,如果我们想要将这些label做出组件,然后复用,有该怎么做呢? 基础组件 首 ...

  4. Springboot+ActiveMQ(ActiveMQ消息持久化,保证JMS的可靠性,消费者幂等性)

    ActiveMQ 持久化设置: 在redis中提供了两种持久化机制:RDB和AOF 两种持久化方式,避免redis宕机以后,能数据恢复,所以持久化的功能 对高可用程序来说 很重要. 同样在Active ...

  5. factory di

    services.AddScoped(typeof(Test)); //services.AddScoped<Test>() // .AddScoped<ITest, Test> ...

  6. asp源码微信扫码授权登陆电脑版

    网站接入微信扫码登录并获取用户基本信息(完美绕过微信开放平台)电脑版网站实现微信扫码登录,注册会员还要设密码太麻烦,会员也记不住密码,采用微信扫码登录网站更方便,会员无需设密码,用他的微信做为系统登录 ...

  7. scikit-learn框架学习笔记(一)

    sklearn于2006年问世于Google,是使用python语言编写的.基于numpy.scipy和matplotlib的一个机器学习算法库,设计的非常优雅,它让我们能够使用同样的接口来实现所有不 ...

  8. Linux高级指令

    一.hostname指令 作用:操作服务器的主机名(读取,设置) #hostname    作用:表示输出完整的主机名 #hostname -f    作用:表示输出当前主机名中的FQDN(权限定域名 ...

  9. JavaScript数组方法--includes、indexOf、lastIndexOf

    我们继续吧! includes:includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false.还是先看看includes的用法吧 var ar ...

  10. OpenCL 矩阵乘法

    ▶ 矩阵乘法,按照书里的内容进行了几方面的优化,包括局部内存,矢量数据类型,寄存器,流水线等. ● 最直接的乘法.调用时 main.c 中使用 size_t globalSize[] = { rowA ...