Skip to content

同步、异步与并发 ​

先理解“等待” ​

后端经常在等数据库、等其他服务、等磁盘。异步允许程序在一次等待期间处理其他可以进行的事情。

可以想象你烧水时顺便洗杯子。烧水总耗时没有因此缩短,但你利用了等待时间。CPU 密集计算则像持续做一道数学题,仅加上 async 不会自动让计算更快。

选 def 还是 async def ​

调用的工具常见选择
同步数据库接口、同步网络请求普通 def 路由,或明确转移阻塞工作
支持 await 的异步数据库/网络工具async def 路由并使用 await
很轻的纯计算、组装字典两者都可,保持简单一致
大量 CPU 计算考虑进程、任务队列或专门计算服务

FastAPI 调用普通 def 路由和普通 def 依赖时,会放到外部线程池执行。你在 async def 中直接调用自己写的普通辅助函数时,不会自动得到同样的线程池转移。官方同步与异步说明

完整示例:异步等待 ​

python
import asyncio
from fastapi import FastAPI

app = FastAPI()


@app.get("/wait")
async def wait_example():
    await asyncio.sleep(1)
    return {"message": "等待完成"}

await asyncio.sleep(1) 在等待期间让出执行机会。它是为了演示等待,真实业务不是靠 sleep 提升性能。

容易出现的阻塞错误 ​

python
# 错误用法的语法片段
# @app.get("/bad")
# async def bad():
#     time.sleep(5)  # 同步阻塞,可能卡住事件循环
#     return {"ok": True}

同样,不要在异步接口中直接调用耗时的同步 HTTP 请求、同步数据库查询或长时间计算,误以为 async def 会自动处理它们。

异步 HTTP 请求示例 ​

追加到本章完整示例,需安装 httpx:

python
import httpx


@app.get("/external-example")
async def external_example():
    async with httpx.AsyncClient(timeout=5.0) as client:
        response = await client.get("https://example.com")
        response.raise_for_status()
    return {"upstream_status": response.status_code}

这里使用固定 URL 展示异步调用;真实项目还需要处理超时与上游失败,频繁调用时可以在应用生命周期中复用客户端。async with 类似 with,用于需要异步清理的资源。HTTPX 异步客户端说明

别把并发与并行混为一谈 ​

并发是让多个任务交替推进;并行是同时执行多个任务。异步主要改善等待场景下的并发。线程、进程、异步是不同工具,适用条件不同。

记忆方法:是否写 async def,取决于你调用的工具是否提供真正的异步操作。

本章练习 ​

解释:为什么在异步接口里执行 time.sleep(5) 与 await asyncio.sleep(5) 的影响不同?

过关标准:不再认为“所有函数加上 async 就会更快”。