生产者-消费者模型

一、是什么

  • 生产者-消费者模型 Producer-Consumer:用线程安全的队列 queue.Queue 解耦“生产数据”的一方和“消费数据”的一方,平衡两者速度差。

  • 生产者往队列 put(),消费者从队列 get();队列时自动阻塞等待。

生活化比喻:工厂流水线——工人 A 把零件放到传送带(生产者),工人 B 从传送带取零件组装(消费者)。传送带就是 Queue:满了 A 就等,空了 B 就等,两人不用互相喊号,节奏自动匹配。

二、为什么需要它

  1. 解耦:生产/消费速率不同也不互相阻塞,各自忙各自的。

  2. 缓冲:突发流量先堆在队列里,消费者按自己节奏处理(背压 backpressure)。

  3. 并发:多线程/多进程可同时生产和消费,提升吞吐。

三、结构图


flowchart LR

    P[生产者线程] -->|put 放入| Q[[Queue\n线程安全队列]]

    Q -->|get 取出| C[消费者线程]

    Q -.队列满 阻塞.-> P

    Q -.队列空 阻塞.-> C

四、可运行代码示例

 
import threading
 
import queue
 
import time
 
import random
 
 
 
q = queue.Queue(maxsize=5)     # 有界队列,满了 put 会阻塞
 
 
 
def producer():
 
    for i in range(5):
 
        time.sleep(random.random())   # 模拟生产耗时不稳定
 
        q.put(i)
 
        print(f"生产 {i}")
 
    q.put(None)                      # 哨兵值:通知消费者结束
 
 
 
def consumer():
 
    while True:
 
        item = q.get()               # 队列空则阻塞等待
 
        if item is None:
 
            q.put(None)              # 多消费者时把哨兵传下去
 
            break
 
        print(f"消费 {item}")
 
        q.task_done()
 
 
 
t1 = threading.Thread(target=producer)
 
t2 = threading.Thread(target=consumer)
 
t1.start(); t2.start()
 
t1.join(); t2.join()
 

五、核心考点

  1. queue.Queue 是线程安全的:内部用了锁 + 条件变量,比手写 list + Lock 省心且不易出错。

  2. 多消费者退出:用哨兵值(如 None)或配合 q.join() + q.task_done() 协同;多消费者时哨兵要在每个消费者间传递。

  3. 这是经典并发模式,也是理解“阻塞队列 / 背压”的基础,分布式系统里 Kafka 等消息队列是其放大版。

  4. 与 GIL 的关系Queue 在等待时释放 GIL,生产者/消费者在等队列时空出 GIL 给彼此,配合良好;真正吃满 CPU 时仍受 GIL 限制(CPU 密集请用多进程或 3.13 自由线程)。


速记卡(面试闪卡)

Q1:一句话讲清「生产者-消费者模型」到底是什么?

A:用线程安全的队列 Queue 解耦生产方和消费方,平衡两者速度差,队列满/空时自动阻塞等待。

Q2:一、是什么 —— 怎么理解? —— 怎么理解?

A:生产者往队列 put()、消费者从队列 get(),中间用 Queue 当”传送带”。好比工厂流水线:工人 A 放零件、工人 B 取零件组装,传送带满了 A 就等、空了 B 就等,两人不用互相喊号,节奏自动匹配。

Q3:二、为什么需要它 —— 怎么理解? —— 怎么理解?

A:三个价值:解耦(生产消费速率不同也不互相阻塞)、缓冲(突发流量先堆队列,消费者按节奏处理=背压 backpressure)、并发(多线程同时生产消费提吞吐)。就像快递柜:快递员随便投,你随便取,不用当面交接。

Q4:三、核心考点 —— 怎么理解? —— 怎么理解?

A:queue.Queue 内部用锁+条件变量,线程安全,比手写 list+Lock 省心。多消费者退出用哨兵值(None)或 q.join()+task_done() 协同。它也是理解阻塞队列/背压的基础,分布式里 Kafka 是其放大版。等队列时释放 GIL,彼此配合良好。

Q5:四、与 GIL 的关系 —— 怎么理解? —— 怎么理解?

A:Queue 在等待时释放 GIL,生产者/消费者等队列时空出 GIL 给对方,配合良好;但真正吃满 CPU 时仍受 GIL 限制——CPU 密集请用多进程或 3.13 自由线程。一句话:I/O 等待场景里,Queue 让 GIL 不再是瓶颈。

Q6:核心速记主线有哪些?

  • Queue 解耦生产方与消费方,平衡速度差

  • 满/空自动阻塞:生产等满、消费等空

  • 三大价值:解耦、缓冲(背压)、并发

  • 多消费者退出用哨兵值或 join/task_done

口诀

A:生产消费排成道,

满等空等节奏好;

解耦缓冲并发跑,

哨兵传话退场早。

相关链接