进程之间的通信

  1. 互斥锁

    进程之间数据不共享,但共享同一套文件系统,或同一个打印终端是没有问题的。但共享导致了竞争,若不加以控制就会造成错乱。如下:

    from multiprocessing import Process
    import time
    import random
    def task1():print('task1开始打印')time.sleep(random.randint(1,3))print('task1打印完成')
    def task2():print('task2开始打印')time.sleep(random.randint(1,3))print('task2打印完成')
    def task3():print('task3开始打印')time.sleep(random.randint(1,3))print('task3打印完成')
    if __name__ == '__main__':p1 = Process(target=task1,)p2 = Process(target=task2,)p3 = Process(target=task3,)p1.start()p2.start()p3.start()
    # task1开始打印
    # task2开始打印
    # task3开始打印
    # task1打印完成
    # task3打印完成
    # task2打印完成

    使用加锁可以使并发变成串行,牺牲效率,避免竞争

    from multiprocessing import Process
    from multiprocessing import Lock
    import time
    import random
    def task1(lock):lock.acquire()print('task1开始打印')time.sleep(random.randint(1,3))print('task1打印完成')lock.release()
    def task2(lock):lock.acquire()print('task2开始打印')time.sleep(random.randint(1,3))print('task2打印完成')lock.release()
    def task3(lock):lock.acquire()print('task3开始打印')time.sleep(random.randint(1,3))print('task3打印完成')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()
    # task1开始打印
    # task1打印完成
    # task2开始打印
    # task2打印完成
    # task3开始打印
    # task3打印完成

    利用多进程抢票:

    from multiprocessing import Process
    from multiprocessing import Lock
    import time
    import random
    import json
    def search():time.sleep(random.random())  # 模拟读取数据网络延迟with open('db.json',encoding='utf-8') as f:dic = json.load(f)print(f'剩余票数{dic["count"]}')
    def get():with open('db.json',encoding='utf-8') as f:dic = json.load(f)time.sleep(random.random())  # 模拟读取数据网络延迟if dic['count'] > 0:dic['count'] -= 1time.sleep(random.random())  # 模拟写数据网络延迟with open('db.json',encoding='utf-8',mode='w') as f:json.dump(dic,f)print(f'{os.getpid()}用户购买成功')else:print('票没了')
    def task(lock):search()lock.acquire()get()lock.release()
    if __name__ == '__main__':lock = Lock()for i in range(5):p = Process(target=task,args=(lock,))p.start()
    # 剩余票数1
    # 剩余票数1
    # 14004用户购买成功
    # 剩余票数0
    # 剩余票数0
    # 票没了
    # 剩余票数0
    # 票没了
    # 票没了
    # 票没了

    虽然可以用文件共享数据实现进程间通信,但问题是:

    1. 效率低(共享数据居于文件,而文件是硬盘上的数据)
    2. 需要自己加锁处理,容易形成死锁、递归锁(注意一个进程只能使用一个锁)
  2. 队列

    multiprocessing模块支持两种形式:队列和管道,这两种方式都是传递数据的。

    队列就是存在于内存中的一个容器,最大的特点就是FIFO,完全支持先进先出原则

    1. 创建队列的类(底层就是以管道和索的方式实现的)

      Queue([maxsize]):创建共享的进程队列,Queue是多进程安全队列,可以使用Queue实现多进程之间的数据传递

    2. 参数介绍

      maxsize是队列中允许最大项数,省略则无大小限制

    3. 方法介绍

      • 主要方法

        # q.put方法用以插入数据到队列中,put方法还有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,该方法会阻塞timeout指定的时间,直到该队列有剩余的空间。如果超时,会抛出Queue.Full异常。如果blocked为False,但该Queue已满,会立即抛出Queue.Full异常。
        # q.get方法可以从队列读取并且删除一个元素。同样,get方法有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,会抛出Queue.Empty异常。如果blocked为False,有两种情况存在,如果Queue有一个值可用,则立即返回该值,否则,如果队列为空,则立即抛出Queue.Empty异常.
        # q.get_nowait():同q.get(False)
        # q.put_nowait():同q.put(False)
        # q.empty():调用此方法时q为空则返回True,该结果不可靠,比如在返回True的过程中,如果队列中又加入了项目。
        # q.full():调用此方法时q已满则返回True,该结果不可靠,比如在返回True的过程中,如果队列中的项目被取走。
        # q.qsize():返回队列中目前项目的正确数量,结果也不可靠,理由同q.empty()和q.full()一样
      • 其他方法

        # q.cancel_join_thread():不会在进程退出时自动连接后台线程。可以防止join_thread()方法阻塞
        # q.close():关闭队列,防止队列中加入更多数据。调用此方法,后台线程将继续写入那些已经入队列但尚未写入的数据,但将在此方法完成时马上关闭。如果q被垃圾收集,将调用此方法。关闭队列不会在队列使用者中产生任何类型的数据结束信号或异常。例如,如果某个使用者正在被阻塞在get()操作上,关闭生产者中的队列不会导致get()方法返回错误。
        # q.join_thread():连接队列的后台线程。此方法用于在调用q.close()方法之后,等待所有队列项被消耗。默认情况下,此方法由不是q的原始创建者的所有进程调用。调用q.cancel_join_thread方法可以禁止这种行为
  3. 进程之间的通信实例

    利用队列进程之间通信:简单,方便,不用自己动手加锁。队列自带阻塞,可持续化取数据。

    # 用队列来存储网络请求,模拟网购抢购
    import os
    from multiprocessing import Queue
    from multiprocessing import Process
    def task(q):try:q.put(f'{os.getpid()}',block=False)  # 模拟存放请求except Exception:return
    if __name__ == '__main__':q = Queue(10)for i in range(100):p = Process(target=task,args=(q,))p.start()for i in range(1,11):print(f'排名第{i}的用户:{q.get()}')    # 获取前十个请求
  4. 生产者与消费者模型

    生产者:生产数据进程

    消费者:对生产者生产出来的数据作进一步处理的进程

    生产者与消费者之间需要有一个容器作为缓冲区,平衡生产力与消费力

    生产者消费者模型多用于并发

    from multiprocessing import Process
    from multiprocessing import Queue
    import time
    import random
    def producer(name,q):for i in range(1,6):time.sleep(random.randint(1,3))ret = f'{i}号包子'q.put(ret)print(f'\033[0;32m 生产者{name}:生产了{ret}\033[0m')
    def consumer(name,q):while 1:try:time.sleep(random.randint(1,3))ret = q.get(timeout=5)print(f'消费者{name}:吃了{ret}')except Exception:return
    if __name__ == '__main__':q = Queue()p1 = Process(target=producer,args=('铁憨憨',q))p2 = Process(target=consumer,args=('皮皮寒',q))p1.start()p2.start()
    # 生产者铁憨憨:生产了1号包子
    #消费者皮皮寒:吃了1号包子
    # 生产者铁憨憨:生产了2号包子
    #消费者皮皮寒:吃了2号包子
    # 生产者铁憨憨:生产了3号包子
    # 生产者铁憨憨:生产了4号包子
    #消费者皮皮寒:吃了3号包子
    # 生产者铁憨憨:生产了5号包子
    #消费者皮皮寒:吃了4号包子
    #消费者皮皮寒:吃了5号包子
  5. 总结

    进程之间的通信:

    1. 基于文件+ 锁的形式: 效率低,麻烦.
    2. 基于队列: 推荐使用形式.
    3. 基于管道: 管道自己加锁, 底层可以会出现数据丢失损坏.

    多个进程抢占一个资源: 串行,有序以及数据安全.

    多个进程实现并发的效果: 生产者消费者模型.

转载于:https://www.cnblogs.com/yaoqi17/p/11240298.html

python之并发编程-进程之间的通信相关推荐

  1. python并发编程--进程、线程、协程、锁、池、队列

    文章目录 操作系统的概念 进程 multiprocessing模块 守护进程 使用多进程实现一个并发的socket的server 锁 生产者消费者模型 数据共享 线程threading模块 守护线程和 ...

  2. 学习笔记(33):Python网络编程并发编程-进程池线程池

    立即学习:https://edu.csdn.net/course/play/24458/296451?utm_source=blogtoedu 进程池与线程池: 一般应用在网站上,进程池或线程池最大的 ...

  3. Python 中的多进程(进程之间的通信)

    文章目录 在进程之间共享数据 共享内存 服务器进程 进程之间的通信 队列 管道 这篇文章将会讲解在 Python 中使用 多进程模块时在进程之间共享数据和消息传递的概念. 在多处理中,任何新创建的进程 ...

  4. python学习并发编程

    一.并发编程理论基础 并发编程得应用: 网络应用:爬虫(直接应用并发编程) 网络架构django.flask.tornado 源码-并发编程 socket server 源码-并发编程 计算机操作系统 ...

  5. Python 3 并发编程多进程之进程同步(锁)

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

  6. 使用Python进行并发编程

    让计算机程序并发的运行是一个经常被讨论的话题,今天我想讨论一下Python下的各种并发方式. 并发方式 线程(Thread) 多线程几乎是每一个程序猿在使用每一种语言时都会首先想到用于解决并发的工具( ...

  7. 并发编程 进程基础

    操作系统 多道 .分时.实时 同步异步 同步:一件事情完成后再做另一件事 异步:同时做多件事 阻塞和非阻塞 阻塞:recv,accept,recvfrom 会让整个进程进入阻塞队列 非阻塞:进程只会在 ...

  8. 『Python学习笔记』Python实现并发编程(补充joblibpymysql)

    Python实现并发编程(补充joblib&pymysql) 文章目录 一. 并发编程知识点 1.1. 为什么引入并发编程 1.2. 如何选择多线程多进程多协程 1.2.1. 什么是CPU密集 ...

  9. Linux 进程及进程之间的通信机制——管道

    参考: LInux C编程从初学到精通 电子工业出版社 Linux 进程 Linux 进程简介 Linux是一个多用户多任务的操作系统,多用户是指多个用户可以在同一时间使用同一台计算机系统:多用户是指 ...

最新文章

  1. 【Python CheckiO 题解】Three Words
  2. 怎么将翼型导入catia_CATIA导入翼型出现了问题,翼型是在网上找的。说是样条线运算有问题 - 机械 - 小木虫 - 学术 科研 互动社区...
  3. C#开发微信门户及应用(28)--微信“摇一摇·周边”功能的使用和接口的实现
  4. PyTorch 深度学习:36分钟快速入门——GAN
  5. mybatis mysql 模糊查询语句_mybatis+Spring mysql的模糊查询问题
  6. VMware Fusion下Centos联网
  7. Java17,有史以来最快 JDK!
  8. bash shell学习的记录(一)
  9. AVG游戏《裂缝》策划案
  10. php源码安装教程宝塔,宝塔版-源码安装教程
  11. 1336:【例3-1】找树根和child
  12. Arduino智能小车——蓝牙小车
  13. 微信官宣:一大波 2022 新年红包封面来了,这波太秀了!!
  14. IEEP部署企业级网络工程-网络故障-环路故障
  15. 计算机专业大专能进什么国企,大专学历可以考哪些国企?
  16. 微信小程序模仿微信主页及页面跳转详解
  17. 同大取大同小取小口诀图解_口诀巧取不等式组的解集
  18. 使用vnc启动服务器candence相关问题
  19. 看看阿里、字节跳动、华为等这些大厂的年终奖都发了多少
  20. MFC中TeeChart插件绘图

热门文章

  1. Unity3D开发之----将预设体Prefab压缩成AssetBundle文件
  2. Mac 直接在word 中使用latex编辑公式
  3. python圣斗士(十七):令人欲罢不能的正则
  4. php怎样转换成html格式,php实现转换html格式为文本格式的方法
  5. ppt.mfa.gov.cn\/appo\/index.html,海外申请护照在线预约网官网登录入口:http://ppt.mfa.gov.cn/ap...
  6. 对称加密和非对称加密;公钥,私钥的理解
  7. Python使用pillow库往图片上写入文字或覆盖另一张图片
  8. 苹果对中国手机产业链有多重要?欧菲光没了它就巨亏27亿
  9. Google镜像网站全(4-3更)
  10. Android随机点名器,Excel基础知识-详解随机点名器