Files
Cloud-book/Python/Python并发编程/协程.md
2025-08-27 17:10:05 +08:00

3.6 KiB
Raw Blame History

协程

协程Coroutine是用户态的轻量级线程由程序自身控制调度通过协作式多任务实现并发。它能在单线程内挂起和恢复执行无需操作系统介入切换开销极小尤其适合 I/O 密集型任务​​(如网络请求、文件读写)。

与线程/进程对比

  • ​资源消耗​​:协程内存占用更低(共享进程内存),线程需独立栈空间,进程资源消耗最大
  • ​切换开销​​:协程切换在用户态完成,速度极快;线程/进程切换依赖操作系统,开销较大
  • 适用场景​​:协程适合高并发 I/O 操作;线程适合 CPU 密集型任务;进程适合多核并行计算

核心优势

  • 高并发​​:单线程可处理数千级并发连接(如 Web 服务器)
  • 无锁机制​​:避免多线程同步问题(如死锁、竞态条件)
  • 代码简洁​​:用同步语法写异步逻辑,避免回调地狱

实现方式

生成器函数

通过 yield 暂停执行并传递值:需要手动管理状态,适用简单场景

def simple_coroutine():
    print("协程启动")
    x = yield  # 暂停点,等待外部传入值
    print(f"接收值: {x}")

coro = simple_coroutine()
next(coro)       # 启动协程,执行到第一个 yield
coro.send(10)    # 恢复执行x 赋值为 10

async/await

通过 asyncio 库实现异步编程

import asyncio


async def fetch_data(url):
    print(f"请求 {url}")
    await asyncio.sleep(1)  # 挂起协程,让出控制权给事件循环,模拟异步等待
    return f"来自 {url} 的数据"


async def main():
    tasks = [fetch_data("url1"), fetch_data("url2")]
    results = await asyncio.gather(*tasks)  #  实现多任务并发调度:并发执行
    print(results)

if __name__ == "__main__":
    asyncio.run(main())

基本语法

定义协程函数

使用 async def 声明协程函数

import asyncio

async def my_coroutine():
    print("协程开始")
    await asyncio.sleep(1)  # 模拟 I/O 操作
    print("协程结束")

运行协程

协程需要通过事件循环执行

async def main():
    await my_coroutine()  # 等待协程完成

if __name__ == "__main__":
    asyncio.run(main())

事件循环

事件循环是协程的调度核心,负责执行、切换和监控协程任务

import asyncio


async def task1():
    print("任务1开始")
    await asyncio.sleep(2)
    print("任务1结束")


async def task2():
    print("任务2开始")
    await asyncio.sleep(1)
    print("任务2结束")


async def main():
    await asyncio.gather(task1(), task2())  # 并发执行多个协程


if __name__ == "__main__":
    asyncio.run(main())

进阶用法

任务

将协程封装为任务,更灵活地控制执行

async def main():
    task = asyncio.create_task(my_coroutine())  # 创建任务
    await task  # 等待任务完成

超时控制

设置协程执行的超时时间

async def slow_task():
    await asyncio.sleep(10)

async def main():
    try:
        await asyncio.wait_for(slow_task(), timeout=3)
    except asyncio.TimeoutError:
        print("任务超时")

协程同步

使用锁 Lock 保护共享资源

lock = asyncio.Lock()

async def safe_write():
    async with lock:  # 异步上下文管理器
        # 安全地操作共享资源
        pass

课后作业

  • [必须] 动手完成本章节案例
  • [扩展] 阅读官方文档相关章节
  • [扩展] 用协程实现进程章节的爬虫案例