You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

asyncio协程触发后暂停至条件满足及锁使用正确性咨询

问题解答

1. 用条件cond2替代10秒延迟的实现方案

直接使用asyncio.Condition这个协程同步原语即可,它专门用于实现"等待某个条件满足后再继续执行"的逻辑,步骤如下:

  • 创建一个所有协程共享的asyncio.Condition实例
  • 当cond1触发时,所有协程进入async with condition:代码块,调用await condition.wait()挂起,直到cond2被触发
  • 当cond2满足时(比如某个状态变更、外部事件触发),在对应的逻辑里执行async with condition:后调用condition.notify_all(),唤醒所有等待的协程

示例代码:

import asyncio

# 模拟cond1和cond2的检查逻辑
def check_cond1(run_count):
    return run_count >= 3

def check_cond2(trigger_flag):
    return trigger_flag

async def coro1(condition, stop_event):
    run_count = 0
    while not stop_event.is_set():
        print("coro1 运行中")
        await asyncio.sleep(1)
        run_count += 1
        
        if check_cond1(run_count):
            print("cond1触发,等待cond2")
            async with condition:
                await condition.wait()  # 挂起直到cond2满足
        print("coro1 恢复运行")

async def coro2(condition, stop_event):
    trigger_flag = False
    run_count = 0
    while not stop_event.is_set():
        print("coro2 运行中")
        await asyncio.sleep(1)
        run_count += 1
        
        if check_cond1(run_count):
            print("coro2触发cond1,等待cond2")
            async with condition:
                await condition.wait()
        
        # 模拟cond2触发逻辑(比如运行5次后触发)
        if run_count >= 5:
            trigger_flag = True
            if check_cond2(trigger_flag):
                async with condition:
                    condition.notify_all()  # 唤醒所有等待的协程
                print("cond2满足,唤醒所有协程")
                stop_event.set()

async def main():
    condition = asyncio.Condition()
    stop_event = asyncio.Event()
    await asyncio.gather(coro1(condition, stop_event), coro2(condition, stop_event))

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

condition.wait()会自动释放内部锁并挂起协程,收到通知后会重新获取锁再恢复执行,完全替代固定延迟的逻辑。

2. asyncio.Lock的正确性排查

你遇到的IO写入干扰,大概率是Lock的使用方式有问题,常见错误及修正方案:

  • Lock实例未共享:如果每个协程自己创建Lock,完全起不到互斥作用,必须让所有需要同步的协程使用同一个Lock实例
  • 原子操作块包裹不全:文件写入的完整流程(打开、写入、关闭)必须全部放在async with lock:块内,不能只锁部分步骤
  • 混用同步IO和异步代码:如果用普通open()做同步写入,即使加了Lock,同步IO会阻塞事件循环,导致协程调度异常,建议用aiofiles这类异步文件库配合Lock

正确的异步文件写入+Lock示例:

import asyncio
import aiofiles

async def safe_write(lock, filename, content):
    # 用Lock包裹整个写入操作
    async with lock:
        async with aiofiles.open(filename, 'a', encoding='utf-8') as f:
            await f.write(content + '\n')

async def coro_a(lock):
    for i in range(5):
        await safe_write(lock, 'log.txt', f'协程A:第{i+1}行内容')
        await asyncio.sleep(0.3)

async def coro_b(lock):
    for i in range(5):
        await safe_write(lock, 'log.txt', f'协程B:第{i+1}行内容')
        await asyncio.sleep(0.3)

async def main():
    # 所有协程共享同一个Lock
    lock = asyncio.Lock()
    await asyncio.gather(coro_a(lock), coro_b(lock))

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

这样就能保证同一时间只有一个协程执行文件写入,避免内容错乱。

内容的提问来源于stack exchange,提问作者bugrahaskan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 14:01:27