互斥锁、共享内存方式以及生产者消费者模型
守护进程
1、守护进程的概念
进程指的是一个正在运行的程序,守护进程也是一个普通进程
意思就是一个进程可以守护另一个进程
import time from multiprocessing import Processdef task():print("子进程 走起!!!")time.sleep(5)print("子进程 挂掉了")if __name__ == '__main__':print("主进程 走起!!!")p = Process(target=task)p.daemon = True # 将子进程设置为守护进程 p.start()time.sleep(3)print("主进程 挂掉了") # --1)如果设置为守护进程,那么主进程一旦结束,那么子进程立马也结束(代码终止执行) # --2)如果没有设置为守护进程,那么主进程结束执行完代码之后,子进程还会继续执行子进程里面的代码
2、结论
如果a 是 b 的守护进程,那么 b 就是被守护的进程, b要是(代码运行完毕)死 ,a也会跟着死
守护进程在主进程代码运行结束之后就死了
3、使用场景
父进程交给了子进程一个任务,任务还没有完成父进程就结束了,子进程就没有继续执行的意义了
例如qq接到一个视频文件,于是开启了一个子进程来下载,如果中途退出了qq,下载任务就没必要继续执行了
互斥锁(重点)
为什么需要互斥锁
当我们同时开启几个子进程的时候,而这几个子进程又要同时操作一个资源(文件或者控制台),
将会导致数据的错乱问题(谁先抢到谁打印,数据混乱看不懂)
解决方案1:
加join (就是每开一个子进程,就加一个join,限制后面的子进程不能开启)
弊端:
--1、把原本并发的任务变成了串行,避免了数据错乱问题,但是效率降低了,
而且是执行完第一个子进程才开启第二个子进程,都放在主程序也是同样效果,没必要开子进程
--2、原本多个进程之间公平竞争,join执行的顺序是定死的,不合理
解决法案2:
给公共资源加锁(互斥锁)
互斥锁,字面理解就是互相排斥的锁,在程序中指的是,如果这个资源已经被锁住了,其他进程就无法使用
需要强调的是:锁,并不是真正的把资源锁起来,只是在代码里加限制,限制你的代码不能执行
import time,random from multiprocessing import Process,Lockdef task1(lock):lock.acquire() # 上锁print('任务一 走起')time.sleep(random.randint(0,2))print('任务一 结束')lock.release() # 解锁def task2(lock):lock.acquire()print('任务二 走起')time.sleep(random.randint(0,2))print('任务二 结束')lock.release()def task3(lock):lock.acquire()print('任务三 走起')time.sleep(random.randint(0,2))print('任务三 结束')lock.release()if __name__ == '__main__':lock = Lock()p1 = Process(target=task1,args=(lock,))p2 = Process(target=task2,args=(lock,))p3 = Process(target=task3,args=(lock,))p1.start()p2.start()p3.start()
注意:
--1、不要对同一代码执行多次acquire,会锁死程序无法执行,一次acquire必须对应一次release
(一次加锁相当于在代码做一次判断,判断成功改状态,再加锁又相当于做一次判断,判断就会失败,锁死)
--2、想要保证数据安全,必须保证所有进程使用同一把锁
(如果每个进程拿到的锁都不一样,那么判断的条件就不会同步)
锁和join的区别
1、join是固定了执行顺序,会造成父进程等待子进程
锁依然是公平竞争,谁先抢到谁先执行,父进程也可以执行其他任务
2、最主要的区别:
join是把进程的所有任务全部串行
锁可以所以任意代码,一行也可以,可以自己调整粒度 粒度(指的是被锁住代码的大小,越小效率越快)
IPC
IPC就是进程间通讯,通讯指的是交换数据
进程之间的内存是相互隔离的,当一个进程想要把数据给另外一个进程,就需要考虑到IPC
IPC方式:
管道:只能单向通讯(一边读,一边写),数据都是二进制
文件:在硬盘上创建共享文件
优点:硬盘的空间大,所以共享的数据量几乎没有限制
缺点:硬盘读取速度慢
socket:编程复杂度高
共享内存: 必须由操作系统来分配 (必须掌握)
优点:速度快
缺点:数据量不能太大
共享内存的方式
1、Manager类
Manager提供了很多数据结构,如list,dict等等(可以在源码中看到)
Manager所创建出来的数据结构,具备进程间共享的特点
from multiprocessing import Manager,Process,Lock import timedef task(dic,lock):lock.acquire() # 这里如果不加锁的话,可能出现多个进程刚取出来的值都是100,然后修改完都是99nums = dic["nums"]# time.sleep(2) # 所有进程拿到100睡2秒,最后修改的数据就是99dic["nums"] = nums - 1lock.release() if __name__ == '__main__':lock = Lock()m = Manager() # 创建一个manager对象dic = m.dict({"nums":100}) # 括号里需要的是一个映射关系,帮我们生成一个进程间共享的字典for i in range(5):p = Process(target=task,args=(dic,lock))p.start()time.sleep(10)print(dic["nums"])
需要注意的是:manager创建的一些数据结构是不带锁的,可能会出现同时修改一个数据的情况,会出问题,不推荐使用、
2、Queue队列 帮我们处理了锁的问题 (重点)
队列是一种特殊的数据结构,先存储的先取出,就像排队,先进的先出
相反的就是堆栈,先存取的后取出,就像把衣服叠进箱子,取的时候先取后叠进去的
函数嵌套调用时,执行的顺序也是先进后出,也称之为函数栈
from multiprocessing import Queueq = Queue(maxsize=3) # 创建一个队列,里面的参数表示的是队列的容量,如果不写默认无限大# 存数据 q.put() 放进去 q.put("a") q.put("b") q.put("c") # q.put("d") # 如果队列里面已经满了,你还继续往里放,他就会进入阻塞状态,一直等到队列有空位置把数据放进去# 取数据 q.get() 拿出来 print(q.get()) print(q.get()) print(q.get()) # print(q.get()) # 同样的,如果队列里面已经空了,你还继续取,它也会进入阻塞状态,一直等到队列里有数据然后取出来 q.get(block=True,timeout=2) # 里面block参数表示的是是否阻塞,默认True(阻塞),当设置为False时,并且队列为空时会立马抛出异常 q.put("aaa",block=True,timeout=2) # 里面block参数表示的是是否阻塞,默认True(阻塞),当设置为False时,并且队列为满时会立马抛出异常 # timeout 表示的时阻塞的超时时间,超过时间还是没有位置或着空的话就会抛出异常
生产者消费者模型 (重点)
1、概念
模型 就是解决某个问题的套路
产生数据的一方称之为生产者
处理数据的一方称之为消费者
例如:饭店厨师就是生产者,吃饭的人就是消费者
2、生产者和消费者产生的问题
生产者和消费者,处理速度不平衡,一方快一方慢,导致一方需要等待另一方再能接着往下执行
3、生产者消费者模型解决这个问题的思路
原本,双方是耦合在一起,消费者必须等待生产着生成完毕再开始处理,反过来,
如果消费者消费速度太慢,生产着必须等待其处理完毕才能开始生成下一个数据
4、解决的方案
将双方分开来,一方专门,负责生产,一方专门负责处理
一样一来,双方的数据就不能直接交互了,双方需要共同的容器
这样就解决了双方能力不平衡的问题,做的快的一方可以继续做,不需要等待另一方,提高了整体的运行效率
from multiprocessing import Process,Queue import time,random def eater(q):for i in range(5):time.sleep(random.randint(0, 2))food = q.get()print("%s吃完了"%food)def cooker(q):for i in ["包子","骨头","土","面","刀子"]:time.sleep(random.randint(0, 2))q.put(i)print("%s做好了"%i)if __name__ == '__main__':q = Queue()cp = Process(target=cooker,args=(q,))ep = Process(target=eater,args=(q,))cp.start()ep.start()
转载于:https://www.cnblogs.com/hesujian/p/10968848.html
互斥锁、共享内存方式以及生产者消费者模型相关推荐
- 三种方式实现生产者-消费者模型
前言 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例.该问题描述了 ...
- python 全栈开发,Day39(进程同步控制(锁,信号量,事件),进程间通信(队列,生产者消费者模型))...
昨日内容回顾 python中启动子进程 并发编程 并发 :多段程序看起来是同时运行的 ftp 网盘 不支持并发 socketserver 多进程 并发 异步 两个进程 分别做不同的事情 创建新进程 j ...
- 锁, threading.local, 线程池, 生产者消费者模型
一. 锁:Lock (1次放1个) 线程安全,多线程操作时,内部会让所有线程排队处理.如:list/dict/Queue 线程不安全 + 人 => 排队处理. 需求: a ...
- 利用互斥锁和条件变量实现生产者消费模型
以下内容全部来自于自旋锁_哔哩哔哩_bilibili #include <stdio.h> #include <pthread.h> #include <stdlib.h ...
- 操作系统:生产者消费者模型的两种实现(C++)
文章目录 生产者消费者模型 什么是生产者消费者模型 生产者消费者模型的321原则 生产者消费者模型的优点 生产者消费者模型的实现方法 基于循环队列,信号量实现 基于阻塞队列,互斥锁.条件变量实现 生产 ...
- 4月25日 python学习总结 互斥锁 IPC通信 和 生产者消费者模型
一.守护进程 import random import time from multiprocessing import Processdef task():print('name: egon')ti ...
- 多线程-生产者-消费者模型
一.前言 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例.该问题描 ...
- Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型...
一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例 ...
- 进程 互斥锁、队列与管道、生产者消费者模型
目录 1.互斥锁 2.队列与管道 3.生产者消费者模型(Queue) 4.生产者消费者模型(JoinableQueue) 1.互斥锁 首先导入Lock模块 实例化一把锁 但是每次生成子进程的时候都会重 ...
最新文章
- vue如何配置服务器端跨域_vue开发环境配置跨域,一步到位
- js生日计算年龄_如何提取身份证生日和年龄,几行VBA代码教你学会
- android java包_android SDk中常用的java包介绍
- containerd镜像导入import和push命令 gzip压缩解压缩命令
- python excel取数 生成报告_python+requests+excel+unittest+ddt接口自动化数据驱动并生成html报告(二)...
- Highly Available (Mirrored) Queues
- 计算机网路【2】数据链路层
- 浅谈href=#与href=javascript:void(0)的区别
- Codeforces Round #179 (Div. 2): D. Greg and Graph(Floyd)
- oracle日期按时间点过滤,Oracle数据库日期过滤方法性能比较
- 安装Java反编译工具Luyten(Windows例)
- 目标检测之RFB-NET(论文翻译辅助阅读)
- Echarts数据可视化总结
- 台式计算机启动时 每次按f1,台式机电脑每次开机都要按F1,华硕主板
- SysTick系统滴答定时器
- android指南针Demo,谁有安卓简易指南针的DEmo
- OPENFILER构建软iSCSI multipath实现多路径聚合(一)
- python输入一个字符串、计算其中小写字符的个数_利用键盘录入,输入一个字符串,统计该字符串中各个字符的数量,并输出(c/c++实现)...
- 在线Base64编码 = 图片
- 【THUWC2019模拟2019.1.18】Counting
热门文章
- python并发编程调优_Python并发编程-并发解决方案概述
- 数组内容转qstring_用Qstring给char[]数组赋值(转)
- haproxy负载均衡_基于mycat+haproxy+keepalived搭建mysql数据库高可用负载均衡
- 继电反馈法自整定_基于继电反馈PID自整定方法在Buck―Boost电路中应用.doc
- python 曲线分析_大数据分析之Python计算KS值并绘制KS曲线
- hikvision v2.3控件网页demo_《快速掌握PyQt5》第三十章 网页交互QWebEngineView
- 戴尔服务器设置文件存储,DELL服务器RAID配置详细教程-20210730001009.pdf-原创力文档...
- php 嵌套 mysql_PHP中实现MySQL嵌套事务的两种解决方案,mysql嵌套_PHP教程
- java condition_死磕Java并发:J.U.C之Condition
- linux安装neo4j及远程访问