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

Python25_进程线程协程

Python25_进程线程协程

文章目录

  • Python25_进程线程协程
    • @[toc]
    • 目录
    • 一、进程(Process)
      • 1.1 基础概念
      • 1.2 创建进程的方式
      • 1.3 进程间通信(IPC)
      • 1.4 进程同步机制
    • 二、线程(Thread)
      • 2.1 基础概念
      • 2.2 GIL 全局解释器锁
      • 2.3 线程创建与同步
      • 2.4 线程池
    • 三、协程(Coroutine)
      • 3.1 基础概念
      • 3.2 asyncio 基础
      • 3.3 协程高级特性
    • 四、核心对比与选择
      • 4.1 三者的本质区别
      • 4.2 选择建议
    • 五、常见问题速查
      • 5.1 进程相关
      • 5.2 线程相关
      • 5.3 协程相关
      • 5.4 综合问题
    • 附录:快速选择指南

本文档系统梳理 Python 并发编程的三大核心机制:进程(Process)线程(Thread)协程(Coroutine),帮助建立完整的知识体系。


目录

  1. 进程(Process)
  2. 线程(Thread)
  3. 协程(Coroutine)
  4. 核心对比与选择
  5. 常见问题速查

一、进程(Process)

1.1 基础概念

Q: 什么是进程?

A:进程是操作系统资源分配的基本单位。每个进程拥有独立的内存空间、代码段、数据段和系统资源。

importosprint(f"当前进程PID:{os.getpid()}")

Q: 进程 vs 程序的区别?

A:

对比项程序进程
本质静态代码动态执行实例
资源不占用占用独立资源
生命周期永久存储创建→执行→销毁
数量一份代码可同时运行多个实例

1.2 创建进程的方式

Q: Python 如何创建进程?

A:主要有三种方式:

# 方式1: multiprocessing 模块(推荐)frommultiprocessingimportProcessimportosdefworker(name):print(f"子进程{name}, PID:{os.getpid()}")if__name__=='__main__':p=Process(target=worker,args=('Alice',))p.start()# 启动进程p.join()# 等待进程结束# 方式2: Process 子类化classMyProcess(Process):defrun(self):print(f"自定义进程, PID:{os.getpid()}")# 方式3: 进程池 PoolfrommultiprocessingimportPooldeftask(n):returnn**2withPool(4)aspool:# 4个进程results=pool.map(task,range(10))

1.3 进程间通信(IPC)

Q: 进程间如何通信?

A:常用两种方式:

方式特点适用场景
Queue先进先出,线程安全生产者-消费者模式
Pipe双向通信,速度较快两个进程间点对点通信
frommultiprocessingimportQueue,Pipe# Queue 示例-先进先出,线程安全(生产者-消费者模式)q=Queue()q.put('数据')item=q.get()# 阻塞式获取# Pipe 示例-双向通信,速度较快(两个进程间点对点通信)parent_conn,child_conn=Pipe()parent_conn.send('Hello')print(child_conn.recv())

1.4 进程同步机制

Q: 进程间如何同步?

A:

frommultiprocessingimportLock,Semaphore# Lock: 互斥锁,保证同一时间只有一个进程访问资源lock=Lock()lock.acquire()# 临界区代码lock.release()# Semaphore: 信号量,控制同时访问的进程数量sem=Semaphore(3)# 最多3个进程同时访问

二、线程(Thread)

2.1 基础概念

Q: 什么是线程?

A:线程是CPU调度的基本单位,同一进程内的线程共享内存空间,切换开销小。

importthreadingprint(f"当前线程:{threading.current_thread().name}")

Q: 线程 vs 进程区别?

A:

对比项进程线程
资源占用独立地址空间共享进程资源
切换开销大(需切换页表)小(只需切换栈)
通信方式需要IPC机制直接读写共享内存
安全性进程间隔离,更安全共享内存,需同步机制
创建速度

2.2 GIL 全局解释器锁

Q: 什么是 GIL?

A:GIL (Global Interpreter Lock) 是 CPython 的特性,确保同一时刻只有一个线程执行 Python 字节码

关键点:

  • 不是 Python 语言的特性,是 CPython 解释器的实现
  • 多线程无法利用多核 CPU进行并行计算(CPU密集型)
  • 多线程适用于I/O 密集型场景(网络请求、文件读写)
# 验证 GIL 存在importsysprint(sys._getframe().f_code.co_filename)# 查看解释器实现

2.3 线程创建与同步

Q: 如何创建线程?

A:

importthreadingimportosimporttime# ==========================================# 方式1: threading 模块(最基础,最常用)# 对应 multiprocessing.Process 的直接调用方式# ==========================================defworker(name):# 注意:线程共享进程的 PID,所以这里 os.getpid() 都是一样的print(f"子线程{name}, TID:{threading.get_ident()}, PID:{os.getpid()}")if__name__=='__main__':# 创建线程对象t=threading.Thread(target=worker,args=('Alice',))t.start()# 启动线程t.join()# 等待线程结束# ==========================================# 方式2: Thread 子类化(面向对象)# 对应 multiprocessing.Process 的子类化方式# ==========================================classMyThread(threading.Thread):defrun(self):# 重写 run 方法,线程启动后会执行这里print(f"自定义线程, TID:{threading.get_ident()}")# ==========================================# 方式3: 线程池 ThreadPoolExecutor (推荐)# 对应 multiprocessing.Pool# 注意:在 Python 3 中,推荐使用 concurrent.futures 模块来实现线程池,# 它比老版的 threading.Thread 手动管理更现代,接口与进程池一致。# ==========================================fromconcurrent.futuresimportThreadPoolExecutordeftask(n):# 模拟耗时操作time.sleep(0.1)returnn**2# 使用上下文管理器自动管理池的创建与销毁withThreadPoolExecutor(max_workers=4)asexecutor:# 最多4个线程并发# map 的用法与 Pool 完全一致results=executor.map(task,range(10))# 如果需要打印结果,list 会阻塞直到所有任务完成print(f"线程池结果:{list(results)}")

Q: 线程同步机制有哪些?

A:

# 1. Lock 互斥锁lock=threading.Lock()withlock:# 上下文管理器pass# 临界区# 2. RLock 可重入锁(同一线程可多次获取)rlock=threading.RLock()# 3. Semaphore 信号量sem=threading.Semaphore(3)# 4. Event 事件通知event=threading.Event()event.wait()# 等待信号event.set()# 发送信号# 5. Condition 条件变量cond=threading.Condition()

2.4 线程池

Q: 为什么要用线程池?

A:减少线程创建/销毁的开销,控制并发数量。

fromconcurrent.futuresimportThreadPoolExecutorimporttimedeftask(n):time.sleep(1)returnn*2withThreadPoolExecutor(max_workers=3)asexecutor:# submit 提交单个任务future=executor.submit(task,5)print(future.result())# 获取返回值# map 批量提交results=executor.map(task,range(10))forrinresults:print(r)

Q: ThreadPoolExecutor 参数详解?

A:

  • max_workers: 最大线程数
  • thread_name_prefix: 线程名前缀
  • initializer: 初始化函数
  • initargs: 初始化参数

三、协程(Coroutine)

3.1 基础概念

Q: 什么是协程?

A:协程是用户态的轻量级线程,由程序员控制调度,而非操作系统内核调度。特点:

  • 单线程内实现并发
  • 切换由程序控制,非操作系统抢占
  • 极高的并发性能(单核支持上万协程)

3.2 asyncio 基础

Q: async def/await 关键字的作用?

A:

  • async def: 定义协程函数
  • await: 挂起当前协程,等待异步操作完成
importasyncioasyncdefhello():print("Hello")awaitasyncio.sleep(3)# 模拟异步操作(这里会被阻塞掉,3s之后再继续执行)print("World")# 运行协程asyncio.run(hello())

Q: 如何并发执行多个协程?

A:

  • asyncio.gather: 并发执行多个协程
asyncdeftask(n):awaitasyncio.sleep(1)returnn**2asyncdefmain():# 方式1: gather 收集结果results=awaitasyncio.gather(task(1),task(2),task(3))# 方式2: Task 对象tasks=[asyncio.create_task(task(i))foriinrange(5)]results=awaitasyncio.gather(*tasks)asyncio.run(main())

3.3 协程高级特性

Q: asyncio 事件循环机制?

A:

importasyncioasyncdefmain():loop=asyncio.get_running_loop()# loop.create_future() # 创建 Future# loop.call_soon() # 立即执行回调# loop.call_later() # 延迟执行

Q: 协程中的同步原语?

A:asyncio 提供了类似线程的同步工具,但协程安全:

# asyncio.Lock() - 协程锁# asyncio.Semaphore() - 协程信号量# asyncio.Event() - 协程事件# asyncio.Condition() - 协程条件变量asyncdefsafe_access(lock):asyncwithlock:# 临界区,同一时间只有一个协程执行pass

四、核心对比与选择

4.1 三者的本质区别

特性进程 Process线程 Thread协程 Coroutine
调度方操作系统内核操作系统内核用户程序/事件循环
切换开销最大(切换页表)中等(切换栈)最小(纯用户态)
数据共享独立内存空间共享进程内存单线程内共享
并行能力✅ 多核并行❌ GIL限制❌ 单线程并发
适用场景CPU密集型I/O密集型高并发I/O
Python实现multiprocessingthreadingasyncio

4.2 选择建议

Q: 什么时候用什么?

A:

CPU密集型(计算-heavy) → 多进程(multiprocessing) ↓ 利用多核CPU I/O密集型(网络/文件-heavy) → 多线程(threading)或 协程(asyncio) ↓ 线程适合中等并发,协程适合超高并发 超高并发(C10K问题) → 协程 + 异步I/O(asyncio + aiohttp) ↓ 单线程管理数万连接

五、常见问题速查

5.1 进程相关

Q: 僵尸进程是什么?如何处理?

A:子进程结束但父进程未回收资源。处理方式:

importosimportsignal# 方式1: 父进程调用 wait()os.wait()# 方式2: 信号处理,自动回收signal.signal(signal.SIGCHLD,signal.SIG_IGN)

Q: 守护进程(Daemon)是什么?

A:主进程结束时自动终止的进程。

p=Process(target=worker)p.daemon=True# 设置为守护进程p.start()

5.2 线程相关

Q: 死锁怎么产生的?如何避免?

A:产生条件(需同时满足):

  1. 互斥条件
  2. 请求与保持
  3. 不剥夺条件
  4. 循环等待

避免方法:

  • 按固定顺序获取锁
  • 使用超时机制
  • 尽量使用with语句管理锁

Q: 线程不安全的表现?

A:

importthreading counter=0defincrement():globalcounter# 非原子操作:读取→修改→写入temp=counter+1# 可能被其他线程打断counter=temp# 解决:加锁或使用原子操作(如 += 实际不是原子操作,需用 Lock)

5.3 协程相关

Q: await 后面可以跟什么?

A:必须是Awaitable对象:

  • 另一个协程(async def)
  • asyncio.Future
  • asyncio.Task
  • 异步I/O操作(如 asyncio.sleep)

Q: 协程中遇到同步阻塞代码怎么办?

A:使用loop.run_in_executor()将同步代码放到线程池执行:

importasyncioimporttimefromconcurrent.futuresimportThreadPoolExecutor executor=ThreadPoolExecutor()asyncdefblocking_io():# 将同步阻塞代码放到线程池执行awaitloop.run_in_executor(None,time.sleep,2)

5.4 综合问题

Q: Python 如何实现真正的并行?

A:只有多进程能实现真正并行(利用多核),因为 GIL 的存在。

frommultiprocessingimportPooldefcpu_task(n):# 模拟CPU密集型计算count=0foriinrange(10**7):count+=1returncount# 多进程并行计算withPool(4)aspool:# 4核并行results=pool.map(cpu_task,range(10))

Q: 并发编程中的最佳实践?

A:

  1. 显式优于隐式:明确控制并发逻辑
  2. 小锁范围:锁的粒度尽量小
  3. 避免共享状态:使用消息传递替代共享内存
  4. 防御性编程:总是考虑异常和超时
  5. 资源清理:使用上下文管理器确保释放

附录:快速选择指南

场景推荐方案关键模块
大量数值计算多进程multiprocessing.Pool
Web 请求爬虫协程 + aiohttpasyncio, aiohttp
文件批量处理线程池ThreadPoolExecutor
实时数据处理多线程 + 队列queue, threading
微服务架构多进程Process + Queue
游戏服务器多进程/多线程混合视具体模块而定

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

相关文章:

  • 暗黑破坏神2存档编辑器:解决角色培养痛点的完整指南
  • AI原生时代的抉择:迈富时的智能体中台战略 - 资讯焦点
  • 3分钟搞定Axure RP中文界面:免费完整汉化指南
  • 2026年全国企业综合服务公司推荐:为华半导体一站式解决方案赋能企业全周期发展 - 资讯焦点
  • 探寻有实力的全域外卖运营服务专业公司,哪家口碑好 - 工业品牌热点
  • TQVaultAE:泰坦之旅无限仓库管理神器,告别背包焦虑
  • 2026年AI学习平台推荐:5大热门平台深度对比,哪个最适合你? - 资讯焦点
  • 深度解析:容器化Android在Linux平台的技术实现与架构设计
  • 不止于数据采集:用Java+Postman玩转OneNET API,打造你的物联网数据中台
  • ECharts-GL 3D地图点击交互避坑指南:解决高亮区域重置与样式冲突问题
  • Python26_并发协程
  • 热议抖音外卖官方品牌服务商哪家好,口碑企业大盘点 - myqiye
  • 基于西门子200smart PLC与昆仑通态触摸屏的真空泵智能运行控制程序
  • 企业级大模型API聚合平台选型Checklist:从PoC到生产的架构考量
  • 如何看懂AIGC检测报告:各指标含义和达标判断方法解读 - 还在做实验的师兄
  • 5分钟快速上手:Windows平台最强C/C++编译器MinGW-w64完全指南
  • LLMWiki研究
  • 从零构建模拟电子系统:核心器件与电路设计实战指南
  • 2026有实力的抖音外卖官方品牌服务伙伴说说怎么收费 - 工业品网
  • Android Studio中文语言包:3分钟打造专属中文开发环境
  • Kali更新报错127.0.0.2?手把手教你清理磁盘空间+永久修复resolv.conf配置
  • 【GitHub开源项目专栏】Google ADK深度解析:多智能体开发的工程化实践
  • 告别库版本困惑:手把手教你区分并获取STM32 MotorControl Workbench 5.4.3的FULL与非FULL版本
  • 终极指南:如何用MetaShark插件完美解决Jellyfin中文影视元数据刮削难题
  • 有实力的抖音外卖官方合作权威品牌服务商探讨,选哪家 - 工业品牌热点
  • 2026年智能客服黑马推荐,值得关注系统与厂商深度测评 - 品牌2026
  • C语言中的变量
  • 【Java】2026 Java学习路线:语言根基(三)★ 核心
  • 如何在foobar2000中实现智能歌词同步?OpenLyrics插件深度解析
  • WSL2 网络困境突围:为 Antigravity 插件构建透明代理隧道