当前位置: 代码网 > it编程>前端脚本>Python > 一文详解Python中queue.Queue和multiprocessing.Queue的区别

一文详解Python中queue.Queue和multiprocessing.Queue的区别

2026年09月04日 Python 我要评论
python 中常见的 queue 有两种:import queueq = queue.queue()from multiprocessing import queueq = queue()它们都提供

python 中常见的 queue 有两种:

import queue

q = queue.queue()
from multiprocessing import queue

q = queue()

它们都提供了 put()get() 等方法,但解决的问题不同。

1.queue.queue

queue.queue 用于同一个进程中的多个线程。

线程共享所属进程的内存,所以它们能够直接操作同一个队列。queue.queue 内部会加锁,避免多个线程同时操作队列时发生数据混乱。

一个进程
├── 线程 a ─┐
├── 线程 b ─┼──> 同一个 queue.queue
└── 线程 c ─┘

示例:

import queue
import threading

q = queue.queue()


def worker():
    q.put("线程写入的数据")


thread = threading.thread(target=worker)
thread.start()
thread.join()

print(q.get())

简单来说,线程就像同一个房间里的人,queue.queue 就像房间里的一个公共盒子。

所有人都能直接操作这个盒子,而队列内部的锁可以避免大家同时操作时发生混乱。

2.multiprocessing.queue

multiprocessing.queue 用于同一台机器上的多个进程。

不同进程拥有各自独立的内存,因此不能直接操作同一个普通 python 队列。

父进程的内存                  子进程的内存

queue.queue a                 queue.queue a 的副本

即使创建子进程时把普通的 queue.queue 传进去,子进程操作的也只是自己内存中的队列,父进程无法看到它后续写入的数据。

multiprocessing.queue 通过操作系统管道在进程之间传输数据:

进程 a
   │
   │ 序列化
   ▼
操作系统管道
   │
   │ 反序列化
   ▼
进程 b

示例:

from multiprocessing import process, queue


def worker(q):
    q.put("子进程写入的数据")


if __name__ == "__main__":
    q = queue()

    process = process(target=worker, args=(q,))
    process.start()

    print(q.get())

    process.join()

可以把多个进程想象成住在不同房间里的人。

他们不能直接操作同一个盒子,所以需要一条传送带,把东西从一个房间送到另一个房间。

multiprocessing.queue 就是这条传送带。

3. 两种 queue 的核心区别

queue.queue

解决的是:多个人在同一个房间里,如何安全地操作同一个盒子。

它依靠共享内存保存数据,并通过线程锁保证操作安全。

一个进程
├── 线程 a ─┐
├── 线程 b ─┼──> queue.queue
└── 线程 c ─┘

multiprocessing.queue

解决的是:人在不同房间里,如何把东西从一个房间送到另一个房间。

它通过序列化、操作系统管道等方式在不同进程之间传递数据。

进程 a ──> 操作系统管道 ──> 进程 b

4. 为什么分布式 manager 使用queue.queue?

在使用 basemanager 实现分布式通信时,真正的队列和数据都保存在 manager 服务端进程里。

其他机器并不会直接操作这个队列,而是通过网络告诉 manager:

请帮我执行 put()

或者:

请帮我执行 get()

例如客户端执行:

q.put("任务 a")

看起来像是在直接操作队列,实际上执行过程是:

客户端
   │
   │ 网络请求:请执行 put("任务 a")
   ▼
manager 服务端
   │
   ▼
服务端执行 queue.queue.put("任务 a")
   │
   ▼
数据保存在服务端进程的内存中

客户端拿到的 q 不是真正的 queue.queue,而是一个代理对象。

这个代理对象负责把客户端的方法调用转换成网络请求。

客户端代理对象
      │
      │ 网络通信
      ▼
manager 服务端
      │
      ▼
真正的 queue.queue

因此,在这种分布式架构中:

  • manager 负责跨进程、跨机器通信;
  • queue.queue 负责在服务端进程中保存数据;
  • 客户端只负责发送操作命令;
  • 真正的 put()get() 都在服务端执行;
  • 数据始终保存在服务端进程中。

5. 多个客户端访问时会发生什么?

多个客户端可以同时向 manager 发送请求:

客户端 a ─┐
客户端 b ─┼── 网络请求 ──> manager 服务端 ──> queue.queue
客户端 c ─┘

manager 服务端可能使用多个线程处理这些请求:

客户端 a ──> manager 服务线程 a ─┐
客户端 b ──> manager 服务线程 b ─┼──> 同一个 queue.queue
客户端 c ──> manager 服务线程 c ─┘

这些服务线程都位于同一个 manager 服务端进程中,因此它们共享服务端进程的内存,也能访问同一个 queue.queue

这正是 queue.queue 擅长处理的情况:

同一个进程中的多个线程
            │
            ▼
     同一个 queue.queue

6. manager 会自动给队列加锁吗?

manager 会保护自己的内部状态,例如:

  • 网络连接;
  • 对象注册信息;
  • 代理对象;
  • 引用计数。

但是,manager 不会自动给注册对象的每个方法加一把全局锁。

也就是说,manager 不会自动执行下面这样的逻辑:

with global_lock:
    task_queue.put("任务")

多个客户端请求可能在不同的 manager 服务线程中同时执行,因此真正保存数据的对象仍然需要保证线程安全。

queue.queue 自己已经实现了线程锁,所以多个 manager 服务线程同时调用它的 put()get() 时,不会把内部数据弄乱。

它们的职责可以这样理解:

manager
   │
   │ 负责把客户端命令送到服务端
   ▼
queue.queue
   │
   │ 负责安全地执行队列操作
   ▼
服务端内存中的数据

因此,不是 manager 自动把普通对象变成了线程安全对象,而是 queue.queue 本身就是线程安全的。

7. 为什么不使用multiprocessing.queue?

不是完全不能使用,而是在典型的 manager 分布式架构中通常没有必要。

manager 已经解决了跨进程、跨机器通信的问题。

如果服务端再使用 multiprocessing.queue,就相当于又增加了一层进程间通信机制。

使用 multiprocessing.queue 时,数据路径类似:

客户端
   │
   │ manager 网络通信
   ▼
manager 服务端
   │
   │ 再进行序列化和管道传输
   ▼
multiprocessing.queue

而使用 queue.queue 时,数据路径更加直接:

客户端
   │
   │ manager 网络通信
   ▼
manager 服务端
   │
   │ 直接操作服务端内存
   ▼
queue.queue

multiprocessing.queue 内部通常还需要:

  • 对数据进行序列化;
  • 使用操作系统管道;
  • 使用进程锁和信号量;
  • 使用后台线程传输数据。

这些机制的目的是让不同进程能够直接传递数据。

但在 manager 分布式架构中,客户端并不直接操作服务端队列。manager 已经把客户端命令传到服务端了,所以没有必要再使用一层进程间管道。

因此:

queue.queue 不是负责分布式通信的,manager 才负责分布式通信。

queue.queue 只是 manager 服务端进程内部保存数据的线程安全容器。

8. 三种场景总结

多线程

一个进程
├── 线程 a ─┐
├── 线程 b ─┼──> queue.queue
└── 线程 c ─┘

使用:

import queue

q = queue.queue()

本机多进程

进程 a ──> 操作系统管道 ──> 进程 b

使用:

from multiprocessing import queue

q = queue()

多机器分布式通信

客户端 a ─┐
客户端 b ─┼──> manager 服务端 ──> queue.queue
客户端 c ─┘

使用:

import queue
from multiprocessing.managers import basemanager

task_queue = queue.queue()

9. 最终结论

选择哪一种 queue,取决于谁在直接操作队列。

同一个进程中的多个线程
    └── queue.queue

本机多个进程直接传递数据
    └── multiprocessing.queue

多个机器通过 manager 访问服务端数据
    └── manager + queue.queue

最重要的理解是:

queue.queue 让同一个进程中的多个线程安全地操作共享数据。

multiprocessing.queue 通过管道把数据从一个进程传递到另一个进程。

在分布式 manager 场景中,客户端并不直接操作队列,只是通过网络向服务端发送命令;真正的队列和数据仍然位于 manager 服务端进程中。

以上就是一文详解python中queue.queue和multiprocessing.queue的区别的详细内容,更多关于python queue.queue和multiprocessing.queue区别的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com