asyncio.event是协程专用的线程不安全同步原语,仅支持set/clear/wait操作且必须在同一线程事件循环中调用;它不传递数据,适合单一布尔信号通知,多协程等待时会同时被唤醒,多次wait需手动clear才能阻塞。

Event对象在asyncio里不是线程安全的,别混用
asyncio.Event 是协程原生的同步原语,和 threading.Event 完全不兼容。如果你在 async def 里 await 一个用 threading.Event 创建的对象,程序会卡死或抛 RuntimeError: cannot be used from a different thread —— 因为 await 期望的是可被事件循环调度的 awaitable,而 threading.Event 没有 __await__ 方法。
正确做法只用 asyncio.Event,且所有 set()、clear()、wait() 都必须在同一个事件循环中调用(通常就是主线程+asyncio.run 启动的那个):
import asyncio
<p>async def waiter(event: asyncio.Event):
print("等待信号...")
await event.wait() # 挂起直到 set()
print("收到信号!")</p><p>async def setter(event: asyncio.Event):
await asyncio.sleep(1)
event.set() # 注意:这里不是 await event.set()</p><p>async def main():
event = asyncio.Event()
await asyncio.gather(waiter(event), setter(event))</p><p>asyncio.run(main())</p>
wait() 不会自动清除状态,多次 await 可能立即返回
asyncio.Event.wait() 是“一次性监听”还是“持续监听”,取决于你是否手动调用 clear()。它只检查当前状态,不改变状态;一旦 set() 被调用过,后续所有 wait() 都会立刻返回,直到你显式 clear()。
- 想实现“每来一次信号就处理一次” → 每次
wait()后紧跟event.clear() - 想实现“首次信号触发后永久生效”(如初始化完成标志)→ 不需要
clear() - 多个协程同时
wait(),全部会在set()后被唤醒,无顺序保证
典型误用:await event.wait(); do_something(); await event.wait() —— 第二次 await 会直接通过,除非中间加了 event.clear()。
set() 和 clear() 是同步方法,但必须在事件循环线程调用
event.set() 和 event.clear() 本身不 await,是普通同步方法,但它们会通知等待中的协程,因此**不能在子线程里直接调用**(比如从 loop.run_in_executor 的函数里调用),否则可能丢通知或引发 RuntimeError。
安全做法只有两种:
- 在协程内直接调用(最常见)
- 从线程中调用时,用
loop.call_soon_threadsafe(event.set)—— 这是唯一跨线程安全的方式
错误示例:
# ❌ 危险:在 executor 线程里直接 event.set()
with concurrent.futures.ThreadPoolExecutor() as pool:
await loop.run_in_executor(pool, lambda: event.set())
<h1>✅ 正确:线程安全投递</h1><p>await loop.run_in_executor(pool, lambda: loop.call_soon_threadsafe(event.set))</p>
Event不适合做带数据的通信,别试图塞 payload
asyncio.Event 只表示“是/否”状态,没有附带数据的能力。有人会想“那我在 set() 前先把数据存到全局变量里”,这不仅破坏封装,还引入竞态:如果多个协程都 wait,谁读哪次 set 对应的数据?根本无法对齐。
真要传数据,该用:
-
asyncio.Queue:天然支持多生产者/多消费者 + 数据传递 -
asyncio.Condition:配合锁,适合更复杂的等待条件(比如“等到某个值大于10”) - 自定义带状态的类 + Event 组合(例如封装
value属性 +event实例)
Event 的定位很窄:就是协程间最轻量的“我好了”“你可以开始了”信号。越想让它干更多事,越容易掉进状态管理的坑里。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











