Loading

进程间通信(生产者消费者模型)

【一】进程间通信介绍

什么是进程间通信

  • 进程间通信(Inter-process Communication,IPC)是指在不同进程之间传输数据或信号的机制。由于每个进程拥有自己独立的内存空间,所以不同进程之间无法直接访问对方的变量或数据结构。因此,操作系统提供了多种IPC机制来允许进程之间共享信息和协调操作。

  • 通俗地理解,可以把进程间通信比作不同办公室之间的沟通。每个办公室(进程)有自己的空间和工作内容,但有时候它们需要交换信息或协调某些行动,这就需要特定的沟通方式(IPC机制)。

常见的IPC机制

  1. 管道(Pipes)
    • 最基本的IPC机制之一。
    • 类似于一根管道,一个进程在管道的一端输入数据,另一个进程从另一端读取数据。
    • 管道通常是单向的,为了双向通信,需要两个管道。
  2. 消息队列(Message Queues)
    • 允许不同进程发送和接收消息。
    • 每个消息都是存储在队列中的数据块,进程可以读写这些消息。

【二】队列介绍

创建队列对象的类(底层就是以管道加锁来实现)

语法:

# 语法
import queue

q = queue.Queue(maxsize)

主要方法:

  • 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()一样

【三】实现进程间通信

模板

from multiprocessing import Process, JoinableQueue
import time
import random


def producer(q, name, food):
    for i in range(1, 8):
        time.sleep(random.randint(1, 2))
        q.put(food)
        print(f'厨师{name}做了{food}')


def consumer(q, name):
    while True:
        food = q.get()
        time.sleep(random.randint(1, 2))
        print(f'顾客{name}吃完了{food}')
        q.task_done()


if __name__ == '__main__':
    q = JoinableQueue()
    p1 = Process(target=producer, args=(q, '德华', '鸡蛋炒河粉'))
    p2 = Process(target=producer, args=(q, '大仙', '大肉面条'))
    c1 = Process(target=consumer, args=(q, 'hqq'), daemon=True)
    c2 = Process(target=consumer, args=(q, 'green'), daemon=True)
    p1.start()
    p2.start()
    c1.start()
    c2.start()
    p1.join()
    p2.join()
    q.join()

  • 这个模板就是以厨师做饭和顾客吃饭为例子
  • 厨师可以做饭(产生数据)----->放到餐桌(加入到队列)
  • 顾客可以在餐桌(队列)----->吃饭(拿到数据)

【四】JoinableQueue类

  • 我的理解是和Queue模块大体不差
  • 用JoinableQueue类示例出来的对象,在每次put或者get都会对管道的数据数量进行计数
  • 当task_done()执行后就会告诉告诉队列他已经从队列里面拿走了一个数据,并且已经处理完了
  • 主进程最后的q.join()就是等待队列中所有的数据被取完,然后再继续往后执行
posted @ 2024-01-18 19:59  HuangQiaoqi  阅读(12)  评论(0编辑  收藏  举报