深入理解 Python 的多进程编程 (Multiprocessing)

在 Python 中,multiprocessing 模块提供了多进程支持,是处理并发任务的一个核心工具。与多线程不同,多进程可以突破 GIL(Global Interpreter Lock,全局解释器锁)的限制,充分利用多核 CPU 进行并行计算。本文将详细介绍 Python 中的多进程编程,包括其基础用法、进程间通信、同步机制,以及与线程和协程的对比。


一、为什么选择多进程?

1. GIL 的限制

Python 的 GIL 限制了多线程的并行能力,同一时间只能有一个线程执行 Python 字节码。对于 CPU 密集型任务,多线程不能充分利用多核 CPU。

多进程通过创建独立的进程,每个进程拥有独立的 GIL,可以并行执行任务,适合需要大量计算的场景。

2. 适用场景

  • CPU 密集型任务:如科学计算、视频处理、大量数据的复杂运算。
  • 任务隔离需求:每个进程有独立的内存空间,减少了竞争资源的风险。

二、multiprocessing 的基础用法

1. 创建子进程

使用 multiprocessing.Process 类可以轻松创建子进程。

from multiprocessing import Process
import osdef worker(task_name):print(f"Task {task_name} is running in process {os.getpid()}")if __name__ == "__main__":process1 = Process(target=worker, args=("A",))process2 = Process(target=worker, args=("B",))process1.start()process2.start()process1.join()process2.join()print("All processes completed")

输出

Task A is running in process 12345
Task B is running in process 12346
All processes completed

2. 进程池(multiprocessing.Pool

当需要管理大量进程时,使用进程池(Pool)可以更方便地分配和调度任务。

from multiprocessing import Pooldef worker(x):return x * xif __name__ == "__main__":with Pool(4) as pool:  # 创建包含 4 个进程的进程池results = pool.map(worker, range(10))print(results)

输出

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

三、进程间通信

Python 提供了多种方式实现进程间通信,包括队列(Queue)、管道(Pipe)和事件(Event)。

1. 使用 Queue

Queue 提供了线程安全的队列,可以实现进程间的数据共享。

from multiprocessing import Process, Queuedef producer(queue):for i in range(5):queue.put(i)print(f"Produced: {i}")def consumer(queue):while not queue.empty():item = queue.get()print(f"Consumed: {item}")if __name__ == "__main__":q = Queue()p1 = Process(target=producer, args=(q,))p2 = Process(target=consumer, args=(q,))p1.start()p1.join()p2.start()p2.join()

输出

Produced: 0
Produced: 1
Produced: 2
Produced: 3
Produced: 4
Consumed: 0
Consumed: 1
Consumed: 2
Consumed: 3
Consumed: 4

2. 使用 Pipe

Pipe 提供了双向通信的能力。

from multiprocessing import Process, Pipedef sender(pipe):for i in range(5):pipe.send(i)print(f"Sent: {i}")pipe.close()def receiver(pipe):while True:try:item = pipe.recv()print(f"Received: {item}")except EOFError:breakif __name__ == "__main__":parent_conn, child_conn = Pipe()p1 = Process(target=sender, args=(parent_conn,))p2 = Process(target=receiver, args=(child_conn,))p1.start()p2.start()p1.join()p2.join()

输出

Sent: 0
Sent: 1
Sent: 2
Sent: 3
Sent: 4
Received: 0
Received: 1
Received: 2
Received: 3
Received: 4

四、进程同步机制

多进程共享资源时需要同步工具,multiprocessing 提供了 LockEvent 等工具。

1. 使用 Lock

Lock 用于防止多个进程同时访问共享资源。

from multiprocessing import Process, Lockcounter = 0def worker(lock):global counterfor _ in range(100000):with lock:counter += 1if __name__ == "__main__":lock = Lock()p1 = Process(target=worker, args=(lock,))p2 = Process(target=worker, args=(lock,))p1.start()p2.start()p1.join()p2.join()print(f"Final counter value: {counter}")

2. 使用 Event

Event 是一种简单的线程同步原语,用于让一个进程等待另一个进程发出信号。

from multiprocessing import Process, Eventdef worker(event):print("Worker waiting for event to be set...")event.wait()  # 等待事件被设置print("Worker received event signal, starting work!")if __name__ == "__main__":event = Event()p = Process(target=worker, args=(event,))p.start()print("Main process performing some setup...")import timetime.sleep(2)print("Main process setting event.")event.set()  # 触发事件p.join()

输出

Worker waiting for event to be set...
Main process performing some setup...
Main process setting event.
Worker received event signal, starting work!

五、多进程、线程与协程的对比

特性多进程(multiprocessing多线程(threading协程(asyncio
适用场景CPU 密集型任务I/O 密集型任务,简单并发I/O 密集型任务,高性能并发
多核支持可充分利用多核受限于 GIL,无多核支持单线程实现并发,无多核支持
资源隔离每个进程独立,资源隔离性高线程共享内存,隔离性较低协程运行在同一线程,隔离性低
资源开销进程上下文切换开销高线程上下文切换开销较低协程更轻量,占用资源更少
通信方式队列(Queue)、管道(Pipe共享内存或队列事件循环或 asyncio.Queue
编程难度相对复杂较简单语法直观,使用方便

六、总结与推荐

  1. 选择多进程

    • 当任务是 CPU 密集型,需要并行处理时,优先考虑 multiprocessing
    • 适合需要进程隔离的场景,避免共享资源引发的数据竞争。
  2. 选择多线程

    • 适用于 I/O 密集型任务,例如文件操作、网络请求。
    • 如果任务需要共享内存并发处理,多线程更方便。
  3. 选择协程

    • 在高并发的 I/O 密集型任务 中(如异步网络请求),协程是最优选择。
    • 轻量、性能高,适合现代异步编程。

通过合理选择工具,可以在 Python 中充分利用多进程、多线程和协程的优势,打造高性能的并发程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/505833.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity自定义编辑器:基于枚举类型动态显示属性

1.参考链接 2.应用 target并设置多选编辑 添加[CanEditMultipleObjects] using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor;[CustomEditor(typeof(LightsState))] [CanEditMultipleObjects] public class TestInspector :…

Qt重写webrtc的demo peerconnection

整个demo为: 可以选择多个编码方式: cmake_minimum_required(VERSION 3.5)project(untitled LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_INCLUDE_CURRENT_DIR ON)set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON)set(CMA…

IOS HTTPS代理抓包工具使用教程

打开抓包软件 在设备列表中选择要抓包的 设备,然后选择功能区域中的 HTTPS代理抓包。根据弹出的提示按照配置文件和设置手机代理。如果是本机则会自动配置,只需要按照提醒操作即可。 iOS 抓包准备 通过 USB 将 iOS 设备连接到电脑,设备需解…

《机器学习》——支持向量机(SVM)

文章目录 什么是支持向量机?基本原理数学模型 支持向量机模型模型参数属性信息 支持向量机实例(1)实例步骤读取数据可视化原始数据使用支持向量机训练可视化支持向量机结果完整代码 支持向量机实例(2)实例步骤导入数据…

高级软件工程-复习

高级软件工程复习 坐标国科大,下面是老师说的考试重点。 Ruby编程语言的一些特征需要了解要能读得懂Ruby程序Git的基本命令操作知道Rails的MVC工作机理需要清楚,Model, Controller, View各司什么职责明白BDD的User Story需要会写,SMART要求能…

使用 Maxwell 计算母线的电动势

三相短路事件的动力学 三相短路事件在电气系统中至关重要,因为三相之间的意外连接会导致电流大幅激增。如果管理不当,这些事件可能会造成损坏,因为它们会对电气元件(尤其是母线)产生极大的力和热效应。 短路时&#x…

Github出现复杂问题 无法合并 分支冲突太多 如何复原

目录 问题再现 解决思路 当然我所指的是在 main 分支开一个新的分支 删除本地文件夹 重新克隆 开一个新分支 切换分支 下载远程分支 文件覆盖 合并到主分支 ​​​​​​​问题再现 太复杂了 无法更改 编译器现状 全部崩溃了 无法更改 即使创建一个新的分支也无济于…

Jenkins触发器--在其他项目执行后构建

前言: jenkins中有多种触发器可用,可以方便的控制构建的启动 这里简单介绍下项目后构建的配置方法 1. 解释: Build after other projects are built Set up a trigger so that when some other projects finish building, a new build is…

CI/CD 流水线

CI/CD 流水线 CI 与 CD 的边界CI 持续集成CD(持续交付/持续部署)自动化流程示例: Jenkins 引入到 CI/CD 流程在本地或服务器上安装 Jenkins。配置 Jenkins 环境流程设计CI 阶段:Jenkins 流水线实现CD 阶段:Jenkins 流水…

计算机毕业设计Python机器学习农作物健康识别系统 人工智能 图像识别 机器学习 大数据毕业设计 算法

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

计算机网络之---物理层设备

什么是物理层设备 物理层设备是指负责数据在物理媒介上传输的硬件设备,它们主要处理数据的转换、信号的传输与接收,而不涉及数据的内容或意义。常见的物理层设备包括网卡、集线器、光纤收发器、调制解调器等。 物理层设备有哪些 1、网卡(N…

HTML实战课堂之简单的拜年程序

一、目录:  一、目录: 二、祝福 三:代码讲解 (1)详细解释: 1.HTML部分 2. CSS部分 三、运行效果(随机截图): 四、完整代码: 二、祝福…

【数据库系统概论】数据库恢复技术

目录 11.1 事务的基本概念 事务的定义 事务的开始与结束 事务的ACID特性 破坏ACID特性的因素 11.2 数据库恢复概述 11.3 故障的种类 1. 事务内部的故障 2. 系统故障 3. 介质故障 4. 计算机病毒 11.4 恢复的实现技术 如何建立冗余数据 数据转储 登记日志文件 11…

Ubuntu问题 -- 硬盘存储不够了, 如何挂载一个新的硬盘上去, 图文简单明了, 已操作成功

需求 我现在有一个ubuntu22.04操作系统的服务器, 但是当前硬盘不够用了, 我买了一个1T的SSD固态硬盘, 且已经安装在服务器上了, 我需要将这个硬盘挂载到当前ubuntu的某个目录上 开始 1. 确认新硬盘是否被系统识别 打开终端,输入以下命令查看系统识别到的硬盘&…

Linux第一个系统程序---进度条

进度条---命令行版本 回车换行 其实本质上回车和换行是不同概念,我们用一张图来简单的理解一下: 在计算机语言当中: 换行符:\n 回车符:\r \r\n:回车换行 这时候有人可能会有疑问:我在学习C…

JavaSE——网络编程

一、InetAddress类 InetAddress是Java中用于封装IP地址的类。 获取本机的InetAddress对象: InetAddress localHost InetAddress.getLocalHost();根据指定的主机名获取InetAddress对象(比如说域名) InetAddress host InetAddress.getByNa…

CompletableFuture // todo

相比较所有代码都在主线程执行,使用Future的好处:利用服务器多核、并发的优势。 不足: 开启没有返回值的异步线程: 1、runAsync 使用lambda表达式: 开启有返回值的异步线程: 1、supplyAsync 异步任务中的…

RabbitMQ基本介绍及简单上手

(一)什么是MQ MQ(message queue)本质上是队列,满足先入先出,只不过队列中存放的内容是消息而已,那什么是消息呢? 消息可以是字符串,json也可以是一些复杂对象 我们应用场…

跟着逻辑先生学习FPGA-第六课 无源蜂鸣器发声实验

硬件平台:征战Pro开发板 软件平台:Vivado2018.3 仿真软件:Modelsim10.6d 文本编译器:Notepad 征战Pro开发板资料 链接:https://pan.baidu.com/s/1AIcnaGBpNLgFT8GG1yC-cA?pwdx3u8 提取码:x3u8 1 知识背景 1.1 蜂鸣器简介 蜂鸣…

TensorFlow Quantum快速编程(高级篇)

五、实战:量子分类器应用 5.1 数据准备 在实战构建量子分类器时,数据准备是基石环节。选用鸢尾花数据集,这一经典数据集在机器学习领域应用广泛,其涵盖了三种鸢尾花品种的样本,每个样本包含花萼长度、花萼宽度、花瓣长度、花瓣宽度四个特征。鉴于本次构建二分类量子分类…