
1. 什么是协程协程Coroutine是一种比线程更轻量级的并发原语。它允许函数在执行过程中挂起suspend并在稍后恢复resume从而实现非阻塞的异步编程。与线程不同协程的调度完全由用户态控制不依赖操作系统的内核调度。这意味着协程的创建和切换开销远小于线程可以在单线程内轻松创建成千上万个协程。2. 进程、线程、协程的对比维度进程线程协程调度方式内核态调度内核态调度用户态调度切换开销最高涉及进程上下文切换较高涉及内核态切换极低仅保存/恢复上下文内存占用独立地址空间占用最大每个线程默认栈空间较大栈空间小可动态增长并发数量受系统资源限制数量最少受系统资源限制可轻松创建数十万级数据竞争进程间相互隔离天然无竞争需要加锁保护共享数据单线程内天然避免竞争通信方式进程间通信IPC共享内存、消息传递共享变量、通道Channel适用场景CPU密集型I/O密集型低并发I/O密集型高并发3. 协程的核心概念3.1 挂起与恢复await关键字协程的核心操作是挂起suspend和恢复resume。当协程遇到耗时操作如网络请求、文件读写时可以主动挂起让出 CPU 给其他协程当操作完成后再恢复执行。3.2 非阻塞协程的挂起不会阻塞线程。在挂起期间线程可以继续执行其他协程从而充分利用 CPU 资源。3.3 运行协程事件循环事件循环是管理和调度所有协程的核心机制。在Python3.7中我们使用asyncio.run()启动事件循环。3.3 结构化并发现代协程框架如 Python 的 asyncio强调结构化并发协程的生命周期与其任务Task绑定主协程会等待所有子协程完成后才结束。3.4 协程的优势调度者协程由程序自身进行调用主动让出CPU给其他协程通过await关键字轻量级创建成本极低一个线程程可以轻松创建数万个协程无锁机制同一时间只有一个协程运行无需锁保护共享资源与线程相比协程避免了操作系统级别的上下文切换开销只有极小的函数调用开销在处理大量I/O操作时效率更高4. 事件循环(Event Loop)详述事件循环是协程并发模型的核心它是负责调度、管理和执行所有协程的“心脏”。其工作流程如下4.1 注册任务注册后协程就被注册到事件循环中等待执行如下3种情况都会实现注册。asyncio.run(main_coro)(顶级注册启动程序)目的启动整个异步程序。机制asyncio.run()负责创建EventLoop并将传入的顶级协程main_coro隐式地包装成一个Task并运行。这个Task成为整个EventLoop的主要任务。用途作为程序的入口点。asyncio.create_task(coro)(最常用实现并发)目的实现并发执行。机制将协程对象coroutine object立即包装成一个Task并将其添加到EventLoop的队列中使其可以立即开始在后台运行而调用者无需等待。用途启动多个任务然后通过asyncio.gather()等待它们的结果。await coro(隐式注册实现串行)目的实现串行等待。机制当EventLoop正在运行一个协程A协程A遇到await coro_B时EventLoop内部会隐式地将coro_B注册为一个任务并开始执行它。但此时EventLoop必须等待coro_B完成才能让A协程恢复执行。用途确保代码按顺序执行。4.2 启动协程事件循环开始运行选择一个就绪的协程开始执行。一 般 是 在 程 序 的 同 步 部 分 通 常 是if__name__“main”: 调 用asyncio.run(main_coroutine) 并 传 入 您 的 顶 级 协 程 对 象 。asyncio.run()负 责 实 例 化 一 个EventLoop对象并将传入的main_coroutine包装成一个Task并将其添加到EventLoop中。调用EventLoop对象的run_until_complete()方法。此时EventLoop进入一个永不停止的while True循环选择第一批就绪任务即main_coroutineTask开始执行。4.3 遇到await协程执行到await关键字表示它即将开始一个耗时的I/O等待。让出控制权协程主动暂停挂起将I/O操作注册到事件循环的监控中然后将控制权交还给事件循环。4.4 切换任务事件循环发现当前协程暂停了它会立即选择下一个处于“就绪”状态的协程继续执行。4.5 I/O完成通知当I/O操作例如3秒的网络等待完成后操作系统会通知事件循环“这个I/O已经准备好了”4.6 恢复协程事件循环将先前挂起的协程重新标记为“就绪”并在合适的时机让它从上次await的地方恢复执行。4.7 终止与清理(TheEnd)EventLoop持续运行上述1-6步。如果EventLoop发现它的顶级Task(main)已经完成它立即触发退出机制。此时EventLoop强制取消所有仍在运行的子Task然后关闭EventLoop程序退出。5.协程的代码示例5.1 Python 协程基础示例importasyncioasyncdeffetch_data():awaitasyncio.sleep(1)# 挂起 1 秒不阻塞线程return数据获取完成asyncdefmain():# 创建并启动一个协程任务taskasyncio.create_task(fetch_data())print(主协程继续执行)resultawaittask# 等待子协程完成print(result)asyncio.run(main())输出 主协程继续执行 数据获取完成5.2 Python 并发任务示例importasyncioasyncdefworker(name,delay):awaitasyncio.sleep(delay)print(f{name}完成)asyncdefmain():# 并发运行多个协程awaitasyncio.gather(worker(任务A,1),worker(任务B,2),worker(任务C,3),)asyncio.run(main())5. 协程的适用场景高并发 I/O 密集型任务如 Web 服务器、爬虫、消息队列消费者。异步网络请求批量请求外部 API 时避免线程阻塞。生产者-消费者模式协程天然适合流式数据处理。状态机与复杂流程控制协程可以简化状态流转逻辑。6. 协程的注意事项协程适合 I/O 密集型任务不适合 CPU 密集型计算此时应使用多进程或线程池。协程内部不能有阻塞调用否则会阻塞整个线程。需要合理控制协程数量避免无限制创建导致内存压力。在调试时协程的调用栈可能不如线程直观需要借助专门的调试工具。7. 总结协程是一种高效的并发编程模型它以极低的切换开销和内存占用为高并发 I/O 场景提供了优雅的解决方案。掌握协程的核心概念和适用场景能够帮助开发者写出更高效、更易维护的异步代码。