Python守护进程、进程互斥锁、进程间通信ICP(Queue队列)、生产者消费者模型
知识点一:守护进程
守护进程:p1.daemon=True
守护进程其实就是一个“子进程“,守护=》伴随
守护进程会伴随主进程的代码运行完毕后而死掉
进程:当父进程需要将一个任务并发出去执行,需要将该任务放到以个子进程里
守护:当该子进程内的代码在父进程代码运行完毕后就没有存在的意义了,就应该
将该子进程设置为守护进程,会在父进程代码结束后死掉
from multiprocessing import Process
import time
def foo():
print(123)
time.sleep(1)
print("end123") def bar():
print(456)
time.sleep(3)
print("end456") if __name__ == '__main__':
p1=Process(target=foo)
p2=Process(target=bar) # 将子进程p1设置为守护进程,
# 所以p1会在print("main-------")打印完成后死掉,所以p1进程不会打印
p1.daemon=True
p1.start()
p2.start()
# time.sleep(1)
print("main-------")
主进程代码运行完,但是主进程不会死,还要回收子进程的僵尸进程,
所有守护进程只是守护主进程代码运行完就会死掉
p.daemon=True #守护进程要放在进程start之前
p.start()
print('主')
(1):正常情况子进程p不会打印,而会直接打印‘主’
(2):个别请况电脑速度快的时候,子类p里面的代码可能会运行(可能不是全部),然后等
主进程打印输出后,p会死掉(代码自上而下运行,操作系统产生并造出子类的速度快的前提下)
知识点二:进程的互斥锁
互斥锁:就是将要执行任务的部门代码(只涉及到修改共享数据的代码)变成串行
第一步:导入multiprocessing方法下面的Lock类
第二步:在if __name__ == '__main__':方法下面调用Lock类mutex=Lock(),拿到一个对象
第三步:在子类中需要共享的数据前后加入 加锁:mutex.acquire()——》需要共享修改数据的代码体《解锁:——mutex.release()
实验:实现简单的抢票功能
分析:1)查看变为并发(实现大家查询到的车票信息是一致的)
2)购买变为串行(因为购买涉及到了修改数据信息,所以一定要遵循先到先得)
(理解为用锁来限制,同一时间只能让一个人拿着锁去改数据,先抢到锁的人
就有优先购买的权限)
join:是将子类里面的所有代码都整体串行(就会将查询、购买2部分全部都变为串行,延迟更高)
互斥锁:可以挑选一段代码(修改数据即买票的那部分)单独抽出来加锁
#模拟抢票软件的原理:
from multiprocessing import Lock,Process
import json,os,time,random def check(): #查票功能实现并行访问
time.sleep(1)
with open('db.txt','rt',encoding='utf-8') as f:
dic=json.load(f)
print('%s 查看余票数为 %s'%(os.getpid(),dic['count'])) def get(): #购票因为牵涉到对后台数据的修改,所以加互斥锁目的是逐一进行访问修改,以免数据错乱
with open('db.txt', 'rt',encoding='utf-8') as f:
dic = json.load(f)
time.sleep(2)
if dic['count'] >0:
#有票
dic['count']-=1
time.sleep(random.randint(1, 3)) #在购票时,模拟网络延迟...
with open('db.txt', 'wt',encoding='utf-8') as f:
json.dump(dic,f)
print('%s 购票成功'%os.getpid())
else:
print('%s 没有余票'%os.getpid()) def task(mutex):
#查看(并行访问)
check()
#抢票(加入互斥锁,实现串行访问,先到先得原则)
mutex.acquire()
get()
mutex.release() #第一个购买完成后,解锁,后续进入继续购买 if __name__ == '__main__':
mutex=Lock() #调用Lock类拿到一个对象
for i in range(10):
p=Process(target=task,args=(mutex,))
p.start()
知识点三:进程间的通信
需求的演变思路:就是为了用一块儿共享的内存==》实现进程间的共享
必须有2个特点:
1.一定是内存空间
2.能够自动帮忙处理锁的问题
IPC机制:
PIPE:管道
Queue:PIPE+锁(队列)
注意:
1.队列占用的是内存空间
2.不应该往队列中放大数据,应该只存放数据量较小的精简的内容
重点讲队列:Queue
同样也是在multiprocessing方法里面导入Queue模块: from multiprocessing import Queue
# q.put()括号里面可以传多种数据类型
#定义队列里面存在数据的个数,先进先出原则 # 1.block、time是搭配使用的
# 2.False:一般单独使用,会立即报错(打印提示信息) q=Queue(3) # #存数据
# q.put('first')
q.put({'k':'second'})
q.put(['two',])
q.put(['three',])
# q.put(4,block=True,timeout=3) #*****如果不加block=True,timeout=3备注,一直是收取的状态
# #block=True timeout:意思是管道满了无法再往里面放,并且会等待3秒
# 如果还是满的状态,就会报错(如果不加程序是一直加载状态不会报错) print(q.get())
print(q.get())
print(q.get())
# print(q.get(block=True,timeout=2)) #***如果不跟参数,会打印前3个,后卡在那里..
#block=True,timeout=2,加了如果管道里面没有数据,等待2秒后会报错(提示信息) #注意无论是收还是发:当block=False的时候,是会直接报错,(所以False一般不与time搭配使用)
# print(q.get(block=False)
知识点四:生产者消费者模型
1.为什么是生产者消费者模型
生产者:比喻的是程序中负责产生数据的任务
消费者:比喻的是程序中负责处理数据的任务
生产者———>共享的介质(队列)<————消费者
2.为何用
实现生产者与消费者的解耦和,生产者可以不停的生产,消费者也可以不停的消费
从而平衡了生产者的生产能力与消费者消费能力,提升了而整体运行的效率
什么时候用:
当我们程序中存在明显的两类任务,一类是负责产生数据,一类是负责处理数据,此时
就应该考虑使用生产者消费者模型来提升程序的效率
第一个初始版本(分析):
from multiprocessing import Queue,Process import time
import os
import random def producer(name,food,q):
for i in range(2):
res='第%s食物%s'%(i,food)
time.sleep(random.randint(1,3))
q.put(res) #往管道传数据
print('\033[45m%s 生产了 %s\033[0m'%(name,res))
# q.put(None) def consumer(name,q):
while True:
time.sleep(random.randint(1, 3))
res=q.get() #从管道取数据
if res is None:break
print('%s 吃了 %s'%(name,res)) if __name__ == '__main__':
q=Queue()
p1=Process(target=producer,args=('生产1','包子',q,))
p2=Process(target=producer,args=('生产2','面条',q,))
p3=Process(target=producer,args=('生产3','米饭',q,)) c1=Process(target=consumer,args=('消费1',q,))
c2=Process(target=consumer,args=('消费2',q,)) #开始造食物
p1.start()
p2.start()
p3.start()
#开始造消费者
c1.start()
c2.start() #保证食物完全造好到管道里面
p1.join() #保证全部生产完,放入管道
p1.join()
p1.join()
q.put(None) #保证所有东西都在管道里面
q.put(None) #2个None是并排放在最后面的,为了保证每个用户进去取完最后取None不至于一致卡在那里接收 print('主程序') #消费者取走了多少,取决于每个消费者网络延迟各方面的速度,另外管道里面的东西取走就没了,搜所以同时取,取得多少是不一定的
终极版本:
#终极版本:消费者给生产者发信号,...等队列结束JoinableQueue,对队列被取空了
from multiprocessing import Queue,Process,JoinableQueue import time
import os
import random def producer(name,food,q):
for i in range(2):
res='第%s食物%s'%(i,food)
time.sleep(random.randint(1,3))
q.put(res) #往管道传数据
print('\033[45m%s 生产了 %s\033[0m'%(name,res)) def consumer(name,q):
while True:
time.sleep(random.randint(1, 3))
res=q.get() #从管道取数据
if res is None:break
print('%s 吃了 %s'%(name,res))
q.task_done() #最终版新增,执行完一次get 就告诉系统有一个数据被取走了 if __name__ == '__main__':
# q=Queue()
q=JoinableQueue() #
p1=Process(target=producer,args=('生产1','包子',q,))
p2=Process(target=producer,args=('生产2','面条',q,))
p3=Process(target=producer,args=('生产3','米饭',q,)) c1=Process(target=consumer,args=('消费1',q,))
c2=Process(target=consumer,args=('消费2',q,)) c1.daemon=True #开始前将子进程设置为守护进程
c2.daemon=True #开始造食物
p1.start()
p2.start()
p3.start()
#开始造消费者 c1.start()
c2.start() #保证食物完全造好到管道里面
# p1.join() #保证全部生产完,放入管道
# p1.join()
# p1.join()
# q.put(None)
# q.put(None) #等所有生产者都生产完了,再执行
p1.join()
p2.join()
p3.join()
#这样就保证一定是队列里面就不会有新东西再放了...
q.join() #等待队列被取干净,执行的同时统计队列里面有多少个值,碰到一个q.task_done()就减1
# 主进程的代码运行完毕--->(生产者运行完毕)+队列中的数据也被取干净了->消费者没有存在的意义 #等到队列取空就执行下一行代码
# print('主程序') #消费者没结束:
#生产者已经结束了,此时就是消费者也已经取完了数据,那么就用到了守护进程
Python守护进程、进程互斥锁、进程间通信ICP(Queue队列)、生产者消费者模型的更多相关文章
- python并发编程之多进程(二):互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型
一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...
- python开发进程:互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型
一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...
- Python学习笔记——进阶篇【第九周】———线程、进程、协程篇(队列Queue和生产者消费者模型)
Python之路,进程.线程.协程篇 本节内容 进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Ev ...
- python 全栈开发,Day39(进程同步控制(锁,信号量,事件),进程间通信(队列,生产者消费者模型))
昨日内容回顾 python中启动子进程并发编程并发 :多段程序看起来是同时运行的ftp 网盘不支持并发socketserver 多进程 并发异步 两个进程 分别做不同的事情 创建新进程join :阻塞 ...
- Python之网路编程之-互斥锁与进程间的通信(IPC)及生产者消费者模型
一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...
- python网络编程--进程(方法和通信),锁, 队列,生产者消费者模型
1.进程 正在进行的一个过程或者说一个任务.负责执行任务的是cpu 进程(Process: 是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在 ...
- 5 并发编程-(进程)-队列&生产者消费者模型
1.队列的介绍 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的 创建队列的类(底层就是以管道和锁定的方式实现 ...
- 进程间通信IPC机制和生产者消费者模型
1.由于进程之间内存隔离,那么要修改共享数据时可以利用IPC机制 我们利用队列去处理相应数据 #管道 #队列=管道+锁 from multiprocessing import Queue # q=Qu ...
- Python连载38-协程、可迭代、迭代器、生产者消费者模型
一.生产者消费者模型 import multiprocessing from time import ctime def consumer(input_q): print("Into con ...
- Python 第九篇:队列Queue、生产者消费者模型、(IO/异步IP/Select/Poll/Epool)、Mysql操作
Mysql操作: grant select,insert,update,delete on *.* to root@"%" Identified by "123456&q ...
随机推荐
- Android 贝塞尔曲线的浅析
博客也开了挺长时间了,一直都没有来写博客,主要原因是自己懒---此篇博客算是给2017年一个好的开始,同时也给2016年画上一个句点,不留遗憾. 那就让我们正式进入今天的主题:贝塞尔曲线. 首先,让我 ...
- Web端 页面跳转 页面传值
要把 Default.aspx 页面 TextBox1中的值 传值到 Default.aspx Label上去 C#服务端跳转页面 Response 响应请求对象 Redi ...
- js进阶之闭包
1.首先说下什么是闭包,闭:封闭,包:就像我们的包包~:虽然我在扯淡但是也有其道理咯,闭包就有点像java里面的封装一样,包属性和方法都封装到对象内部,在外部通过共有的get.set方法获取或者设置其 ...
- Cocos2d-x数据相关的类用法简介(附示例)
(搬运自我在SegmentFault的博客) 在Cocos2d-x的学习和使用中,我遇到了很多关于数据的操作.在这个过程中,我学习了Cocos2d-x自带的很多功能.下面我把接触到的类罗列在下面,给出 ...
- vue-cli版本更新(2.9.1)问题记录-2
今天想把做好的页面放在手机端浏览,发现新版的vue-cli无论在PC还是手机都只能用localhost访问(127.0.0.1除外).....(这样还怎么让我用手机吃鸡了!TT),于是我在网上查找了一 ...
- HDU 5090 Game with Pearls (贪心)
一道贪心的题,因为最小的不能由别的转化,所以每次贪心找最小的,其余的转化成大的. 从小到大,最小的如果不存在那么就break,否则减去一个,剩下的加k继续判断. #include<cstdio& ...
- appium---常用的adb命令
在测试android-app的时候,adb命令可以帮助我们解决许多问题 什么是adb Android Debug Bridge,我们一般简称为adb,主要存放在sdk安装目录下的platform-to ...
- STM32F042开发板学习实践
之前有粗略地学习过stm32F103的理论知识,但仅GPIO的配置.时钟配置就让人望而却步.现在手头有Nucleo STM32F042的开发板,而且ST已经推出STM32CubeMx图形化的工具软件, ...
- c3p0,dbcp和proxool
关于c3p0.dbcp和proxool,之类的比较,配置在网上有很多的文章,我这边就不浪费大家的时间了,主要讲下我用过这三个之后的体会. dbcp:框架以前使用的是dbcp,网上说,有很多BUG,至少 ...
- java中异常处理机制 throw抛出自定义业务逻辑异常 throws继续抛出 catch捕获后会自动继续抛向调用方法
package com.swift; public class Exception_TestC { public static void main(String[] args) { /* * 第5题: ...