守护进程

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

互斥锁、共享内存方式以及生产者消费者模型相关推荐

  1. 三种方式实现生产者-消费者模型

    前言 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例.该问题描述了 ...

  2. python 全栈开发,Day39(进程同步控制(锁,信号量,事件),进程间通信(队列,生产者消费者模型))...

    昨日内容回顾 python中启动子进程 并发编程 并发 :多段程序看起来是同时运行的 ftp 网盘 不支持并发 socketserver 多进程 并发 异步 两个进程 分别做不同的事情 创建新进程 j ...

  3. 锁, threading.local, 线程池, 生产者消费者模型

    一. 锁:Lock (1次放1个) 线程安全,多线程操作时,内部会让所有线程排队处理.如:list/dict/Queue     线程不安全 + 人 => 排队处理. 需求:         a ...

  4. 利用互斥锁和条件变量实现生产者消费模型

    以下内容全部来自于自旋锁_哔哩哔哩_bilibili #include <stdio.h> #include <pthread.h> #include <stdlib.h ...

  5. 操作系统:生产者消费者模型的两种实现(C++)

    文章目录 生产者消费者模型 什么是生产者消费者模型 生产者消费者模型的321原则 生产者消费者模型的优点 生产者消费者模型的实现方法 基于循环队列,信号量实现 基于阻塞队列,互斥锁.条件变量实现 生产 ...

  6. 4月25日 python学习总结 互斥锁 IPC通信 和 生产者消费者模型

    一.守护进程 import random import time from multiprocessing import Processdef task():print('name: egon')ti ...

  7. 多线程-生产者-消费者模型

    一.前言 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例.该问题描 ...

  8. Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型...

    一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例 ...

  9. 进程 互斥锁、队列与管道、生产者消费者模型

    目录 1.互斥锁 2.队列与管道 3.生产者消费者模型(Queue) 4.生产者消费者模型(JoinableQueue) 1.互斥锁 首先导入Lock模块 实例化一把锁 但是每次生成子进程的时候都会重 ...

最新文章

  1. vue如何配置服务器端跨域_vue开发环境配置跨域,一步到位
  2. js生日计算年龄_如何提取身份证生日和年龄,几行VBA代码教你学会
  3. android java包_android SDk中常用的java包介绍
  4. containerd镜像导入import和push命令 gzip压缩解压缩命令
  5. python excel取数 生成报告_python+requests+excel+unittest+ddt接口自动化数据驱动并生成html报告(二)...
  6. Highly Available (Mirrored) Queues
  7. 计算机网路【2】数据链路层
  8. 浅谈href=#与href=javascript:void(0)的区别
  9. Codeforces Round #179 (Div. 2): D. Greg and Graph(Floyd)
  10. oracle日期按时间点过滤,Oracle数据库日期过滤方法性能比较
  11. 安装Java反编译工具Luyten(Windows例)
  12. 目标检测之RFB-NET(论文翻译辅助阅读)
  13. Echarts数据可视化总结
  14. 台式计算机启动时 每次按f1,台式机电脑每次开机都要按F1,华硕主板
  15. SysTick系统滴答定时器
  16. android指南针Demo,谁有安卓简易指南针的DEmo
  17. OPENFILER构建软iSCSI multipath实现多路径聚合(一)
  18. python输入一个字符串、计算其中小写字符的个数_利用键盘录入,输入一个字符串,统计该字符串中各个字符的数量,并输出(c/c++实现)...
  19. 在线Base64编码 = 图片
  20. 【THUWC2019模拟2019.1.18】Counting

热门文章

  1. python并发编程调优_Python并发编程-并发解决方案概述
  2. 数组内容转qstring_用Qstring给char[]数组赋值(转)
  3. haproxy负载均衡_基于mycat+haproxy+keepalived搭建mysql数据库高可用负载均衡
  4. 继电反馈法自整定_基于继电反馈PID自整定方法在Buck―Boost电路中应用.doc
  5. python 曲线分析_大数据分析之Python计算KS值并绘制KS曲线
  6. hikvision v2.3控件网页demo_《快速掌握PyQt5》第三十章 网页交互QWebEngineView
  7. 戴尔服务器设置文件存储,DELL服务器RAID配置详细教程-20210730001009.pdf-原创力文档...
  8. php 嵌套 mysql_PHP中实现MySQL嵌套事务的两种解决方案,mysql嵌套_PHP教程
  9. java condition_死磕Java并发:J.U.C之Condition
  10. linux安装neo4j及远程访问