asyncio.lock 是协程安全锁,确保同一时刻仅一个协程执行受保护代码;需用 await acquire() 和 release() 或更推荐的 async with 语法;不可重入、不跨事件循环复用、不阻塞事件循环。

asyncio.Lock 是什么
asyncio.Lock 是 asyncio 提供的协程安全锁,用于在异步环境中控制对共享资源的并发访问。它和线程中的 threading.Lock 类似,但专为 await 语法设计,不能用在同步代码里,也不能被普通 time.sleep 或 print 等阻塞操作“穿透”。它的核心作用是:**确保同一时刻只有一个协程能执行某段受保护的代码**。
基本用法:await acquire() + try/finally
创建锁后,需显式 await 获取、显式释放。推荐用 try/finally 保证释放,避免因异常导致死锁:
示例:
lock = asyncio.Lock()
await lock.acquire()
try:
# 执行需要独占的操作,比如更新全局计数器、写文件、调用限频 API
shared_counter += 1
finally:
lock.release()
立即学习“Python免费学习笔记(深入)”;
更简洁写法:用 async with
asyncio.Lock 支持异步上下文管理协议,推荐优先使用 async with,自动处理获取与释放:
- 代码更短,不易漏掉 release
- 即使内部抛出异常,锁也会被正确释放
- 语义清晰,明确标出临界区范围
示例:
lock = asyncio.Lock()
async with lock:
shared_counter += 1
await asyncio.sleep(0.1) # 模拟异步 I/O
注意点和常见误区
- 不能跨 Task 复用 lock 实例:一个 lock 对象可被多个协程 await,但必须是同一个事件循环里的任务;不同 loop(如多进程里各自创建的 loop)不能共用
- 不可重入:同一线程或同一协程中重复 await acquire() 会永远挂起(除非先 release),不支持递归加锁
- 不阻塞事件循环:await lock.acquire() 是挂起当前协程,把控制权交还给 event loop,其他协程可继续运行,不是“忙等”
- 没有超时参数(原生 Lock):若需超时,可用 asyncio.wait_for(await lock.acquire(), timeout=2),或改用 asyncio.Semaphore(更灵活)










