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

Python【协程(Coroutine)和线程的关系】

        协程(Coroutine)和线程都是实现并发编程的技术,但它们在实现方式、使用场景和性能上有显著区别。理解它们的关系与差异有助于在实际应用中选择合适的并发模型,以下是它们的核心关系与对比分析:

一、核心关系

  1. 互补关系
    协程和线程可以结合使用(如一个线程内运行多个协程,或多个线程各自运行协程)。

  2. 替代关系
    在I/O密集型场景中,协程常被用来替代线程以减少资源开销。

  3. 层次关系
    协程是用户态的"轻量级线程",线程是操作系统调度的基本单位。

生活化的比喻来解释:快餐店点餐

线程版餐厅(传统多线程)

  • 每个顾客(任务)配一个专属服务员(线程)

  • 服务员A带顾客1点餐 → 等厨师做汉堡(线程阻塞)

  • 服务员B带顾客2点餐 → 等可乐机打饮料(线程阻塞)

  • 问题
    1个顾客发呆时,他的服务员只能干等着,不能服务其他人
    雇100个服务员(线程)成本太高(内存爆炸)

协程版餐厅(异步协程)

  • 1个超级服务员(事件循环)服务所有顾客

  • 带顾客1点汉堡 → 记下"等3分钟" → 立刻服务顾客2
    顾客2要可乐 → 记下"等1分钟" → 检查顾客1的汉堡好了没...

  • 优势
    1个服务员搞定全场!谁的食物好了就继续服务谁

二、关键对比

特性协程 (Coroutine)线程 (Thread)
调度方用户程序控制(事件循环)操作系统内核调度
切换成本极低(仅寄存器保存)高(需要内核态/用户态切换)
内存占用通常KB级通常MB级(默认栈大小)
并发数量轻松支持数万级通常数百到数千
并行能力单线程内并发,需多线程实现并行可利用多核CPU
阻塞影响一个协程阻塞会阻塞整个事件循环一个线程阻塞不影响其他线程
适用场景I/O密集型(网络请求、文件读写等)CPU密集型或混合型任务
典型实现Python asyncio、Go goroutinePython threading、Java线程

生活化的比喻来解释核心区别总结:

线程协程
员工雇佣大量服务员1个超人服务员
成本工资高(内存占用大)工资低(内存占用小)
效率经常站着等(阻塞)永远在忙(非阻塞)
规模最多几百人能接待数万人

三、技术原理差异

1. 线程的实现

  • 内核调度:线程切换需要CPU从用户态切换到内核态

  • 抢占式调度:操作系统决定何时切换线程

  • 同步问题:必须使用锁等机制解决资源竞争

    # Python线程示例
    import threadingdef task():print("Thread running")thread = threading.Thread(target=task)
    thread.start()

2. 协程的实现

  • 用户态调度:通过事件循环(Event Loop)管理

  • 协作式调度:协程主动让出控制权(通过await

  • 单线程内并发:通过状态保存/恢复实现

    # Python协程示例
    import asyncioasync def task():print("Coroutine running")asyncio.run(task())

四、典型协作模式

1. 单线程+多协程(经典异步模型)

async def fetch(url):print(f"Start fetching {url}")await asyncio.sleep(1)  # 模拟I/Oprint(f"Finished {url}")async def main():await asyncio.gather(fetch("url1"),fetch("url2")  # 两个协程并发执行)asyncio.run(main())

输出:

Start fetching url1
Start fetching url2
Finished url1
Finished url2

2. 多线程+每线程多协程(高并发服务)

async def handle_connection(reader, writer):data = await reader.read(100)writer.write(data)await writer.drain()async def thread_main():server = await asyncio.start_server(handle_connection, '127.0.0.1', 8888)async with server:await server.serve_forever()# 每个线程运行独立的事件循环
def start_thread():asyncio.run(thread_main())threads = [threading.Thread(target=start_thread) for _ in range(4)]
for t in threads: t.start()

五、如何选择?

使用协程当:

  • 需要高并发I/O操作(如Web服务器)

  • 希望减少内存开销

  • 需要精细控制执行流程

  • 避免锁的复杂性(单线程内协程无需锁)

    使用线程当:

  • 需要利用多核CPU(计算密集型任务)

  • 调用阻塞式第三方库(如某些数据库驱动)

  • 需要操作系统级别的并行

    混合使用建议:

  • 用协程处理I/O密集型任务

  • 用线程池处理CPU密集型任务

  • 例如:FastAPI等框架使用线程池+协程的混合模式

现实场景
协程:适合网络请求(比如同时爬1万个网页)
→ 就像服务员在等网页响应时,可以先去处理其他请求

线程:适合计算任务(比如视频转码)
→ 必须真的用多个厨师(CPU核心)同时干活

六、性能对比实验

import asyncio
import threading
import time# 协程版本
async def coroutine_task(id):await asyncio.sleep(1)async def coroutine_main():tasks = [coroutine_task(i) for i in range(1000)]await asyncio.gather(*tasks)# 线程版本
def thread_task(id):time.sleep(1)def thread_main():threads = []for i in range(1000):t = threading.Thread(target=thread_task, args=(i,))t.start()threads.append(t)for t in threads: t.join()# 测试执行
start = time.time()
asyncio.run(coroutine_main())
print(f"Coroutines: {time.time()-start:.2f}s")start = time.time()
thread_main()
print(f"Threads: {time.time()-start:.2f}s")

输出

Coroutines: 1.02s  # 1000个协程并发
Threads: 1.05s    # 1000个线程竞争资源

七、现代发展趋势

  1. 协程成为主流:Go的goroutine、Python asyncio、Rust tokio等

  2. 线程角色转变:更多作为协程的底层支撑(如CPU密集型任务)

  3. 混合编程模型

    • 使用协程处理高并发I/O

    • 使用线程池处理阻塞/计算任务

    • 使用多进程利用多核

理解两者的关系和差异,能帮助开发者根据场景选择最佳并发方案。

八、终极结论

  • 需要等别人(IO操作)时 → 用协程(省钱高效)

  • 需要真干活(CPU计算)时 → 用线程/进程(利用多核)

就像餐厅:
人多但都只是点单 → 1个超人服务员(协程)
真的要做100道菜 → 必须雇多个厨师(线程/进程)

相关文章:

  • 为什么栈内存比堆内存速度快?
  • .dat 文件一般可以用什么打开
  • Java 序列化与反序列化
  • 支持私有化部署的电子合同平台——一合通
  • RAG5个常见错误
  • Codeforces Round 1020 (Div. 3)(题解ABCDEF)
  • 如何使用@KafkaListener实现从nacos中动态获取监听的topic
  • 浏览器环境下JS执行机制
  • 解锁大数据新视野:构建强大可观测平台
  • femap许可常见问题及解决方案
  • 数字域残留频偏的补偿原理
  • DeepSeek本地部署手册
  • 7.10 GitHub Sentinel CLI开发实战:Python构建企业级监控工具的5大核心技巧
  • canvas画板!随意画!!
  • C语言标准库函数setlocale用法详解
  • 自定义异常处理(全局异常处理)
  • 用python进行OCR识别
  • 《解锁LLMs from scratch:开启大语言模型的探索之旅》
  • “生成式AI大模型、多模态技术开发与应用”学习
  • 谈谈接口和抽象类有什么区别?
  • 巴黎奥运后红土首秀落败,郑钦文止步马德里站次轮
  • 面对面倾听群众意见建议,及时回应解决群众“急难愁盼”问题!龚正在基层开展下访活动,调研城市更新
  • 释新闻|印度宣布“掐断”巴基斯坦水源,对两国意味着什么?
  • 当哲学与戏剧作为一种生活方式——《人生六戏》分享会
  • 证券时报:落实“非禁即入” ,让创新活力充分涌流
  • 商务部:美方应彻底取消所有对华单边关税措施