当前位置: 首页 > news >正文

下篇:Python 多任务编程入门(二)—— 进程同步、进程池与注意事项

目录

一、进程间的资源竞争与锁

1. 进程锁(Lock)的作用

2. 使用步骤

3. 代码示例

二、进程池:高效管理大量子进程

1.进程池的原理

2. 核心方法

3. 示例:用进程池批量计算平方

三、多进程编程的重要注意事项

1. 全局变量不共享

2. 主进程与子进程的结束顺序

四、总结:什么时候该用进程?


一、进程间的资源竞争与锁

虽然进程之间默认不共享内存,但当它们同时访问同一个外部资源(如同一个文件、同一台打印机、同一个网络端口)时,仍然会产生冲突。例如,两个进程同时向同一个文件写入数据,可能会造成数据错乱。

1. 进程锁(Lock)的作用

就像一个门上的锁:谁拿到钥匙,谁就进去使用资源,其他人只能在门外等待。这样就能保证同一时间只有一个进程操作共享资源。

2. 使用步骤

  • 创建锁:lock = multiprocessing.Lock()

  • 在子进程中获取锁:lock.acquire()(如果锁已被占用,当前进程会阻塞)

  • 释放锁:lock.release()(通常放在finally中,确保一定释放)

3. 代码示例

import multiprocessing import time def task(lock, name): lock.acquire() try: print(f"{name} 获得锁,开始工作") time.sleep(1) print(f"{name} 工作完成") finally: lock.release() if __name__ == '__main__': lock = multiprocessing.Lock() p1 = multiprocessing.Process(target=task, args=(lock, '进程1')) p2 = multiprocessing.Process(target=task, args=(lock, '进程2')) p1.start() p2.start() # 进程1 获得锁,开始工作 # 进程1 工作完成 # 进程2 获得锁,开始工作 # 进程2 工作完成

运行结果会看到两个进程不会同时打印“开始工作”,而是先后执行。

注意:同一个进程内,不能连续两次调用acquire()而不释放,否则会导致死锁(程序卡住)。

二、进程池:高效管理大量子进程

假如你要执行 100 个短小的任务,每个任务只耗时 0.1 秒。如果为每个任务创建一个进程,创建和销毁进程的开销可能远大于任务本身。这时,进程池(Pool)是更优方案。

1.进程池的原理

进程池预先创建一批固定数量的子进程(比如 4 个),然后把任务丢给它们。一个任务完成后,该进程并不销毁,而是去执行下一个任务。这样可以避免频繁创建/销毁进程的代价。

2. 核心方法

  • Pool(processes=n):创建进程池,最多同时运行 n 个进程。

  • apply_async(func, args, kwargs):异步提交任务(推荐),主进程不等待。

  • map(func, iterable):批量提交,类似内置map,会阻塞直到全部完成。

  • close():关闭进程池,不再接受新任务。

  • join():等待池中所有任务执行完毕。

3. 示例:用进程池批量计算平方

import multiprocessing import os def square(x): print(f"进程 {os.getpid()} 计算 {x} 的平方 = {x*x}") return x*x if __name__ == '__main__': with multiprocessing.Pool(processes=4) as pool: results = pool.map(square, range(10)) print("所有结果:", results)

with语句会自动调用close()join(),非常方便。

三、多进程编程的重要注意事项

1. 全局变量不共享

每个进程有独立的内存空间,子进程会拷贝主进程的全局变量,但修改子进程中的变量不会影响主进程,反之亦然。如果需要进程间通信,请使用QueuePipe或共享内存。

2. 主进程与子进程的结束顺序

默认情况下,主进程会等待所有子进程结束后才退出。如果你希望主进程退出时立即终止所有子进程,有两种方法:

  • 守护进程:设置p.daemon = True,主进程结束时会自动杀死守护子进程。

p = multiprocessing.Process(target=func) p.daemon = True p.start()
  • 手动终止:调用p.terminate()强制结束子进程。
p.terminate() # 立即终止子进程

四、总结:什么时候该用进程?

  • CPU 密集型任务(如图像处理、大量数学计算):进程能利用多核 CPU,效果显著。

  • 任务相互独立,不需要频繁通信:进程天然隔离,安全可靠。

  • 大量短任务:配合进程池,避免频繁创建销毁的开销。

如果任务主要是 I/O 密集型(如网络请求、文件读写),线程或协程可能更轻量。但无论如何,掌握进程编程是 Python 多任务进阶的必经之路。

下篇核心回顾

  • 进程锁(Lock)解决资源竞争。

  • 进程池(Pool)高效管理大量子进程。

  • 全局变量不共享,主进程与子进程的结束方式需留意。

http://www.jsqmd.com/news/668838/

相关文章:

  • leetcode热题 - 3
  • 力扣-142.环形指针
  • Delphi 10.4.2 实战:手把手教你用FMXLinux在Ubuntu上跑通第一个GUI程序
  • 从kHz到EHz:揭秘频率单位阶梯的换算逻辑与工程应用场景
  • Django 后台导出数据功能的实现
  • Gemini出点问题-----解决
  • 手写一个最小 Starter:从 0 到能看懂
  • 考研复习Day 16 | 数据结构与算法 --树与二叉树(上)
  • AI Agent Harness Engineering 的部署架构:单体部署、分布式部署与混合云
  • 终极BT下载加速指南:每天更新的Tracker列表让你的下载速度翻倍
  • FastAPI 项目 PyInstaller 打包 exe 全踩坑根治教程(Windows 全电脑通用分发)
  • 企业云盘选型标准合同条款:数据归属/服务等级/SLA全解析
  • 探究分享从对话到执行:OpenTiny NEXT 如何重塑前端智能化开发范式
  • STM32 IAP升级踩坑实录:BootLoader跳转失败、向量表重置、Flash分区冲突,我是如何解决的?
  • ControlSizePyQt - PyQt 版本的统一尺寸和颜色管理系统
  • 网络工程师必看:H3C与华为认证体系的前世今生及备考选择指南
  • 淘一个二手铷原子钟并用起来的过程
  • 从卖不出去到月入15000,贵阳这两家公司凭什么让销售翻身? - 精选优质企业推荐官
  • 一文看懂推荐系统:排序09:Field-aware Factorization Machines (FFM) 的工业界冷思考:为何从FM到FFM的改进叫好不叫座?
  • uni-app怎么实现弹窗 uni-app自定义模态框遮罩层【代码】
  • ESP32上传图片到巴法云,除了HTTPClient,你还可以试试这个库
  • 频谱分析仪
  • Qt Quick项目实战:用KDDockWidgets 1.4.0为你的QML界面添加可拖拽停靠面板(附源码)
  • C语言学习日志
  • 学习分享数据结构对比
  • Spring Boot 自动装配原理(面试版 + 实战理解版)
  • 老年人扎堆学AI,背后藏着千亿级银发经济新蓝海
  • 别再让Quartus默认的1GHz时钟坑了你!手把手教你为FPGA点灯工程写SDC约束文件
  • 通风系统节能改造笔记:用PLC分段控制替代PID,稳定风压还省电(含现场数据对比)
  • 【2026年最新600套毕设项目分享】微信小程序的小说实体书商城(30106)