关于Python中线程与异步结合场景下函数并行执行的疑问
关于Python中线程与异步结合场景下函数并行执行的疑问
先给你明确答案:你当前代码里的这两个函数并没有并行执行。
为啥呢?你看main里的max(do_sync(1), await do_async(2))这行:
do_sync(1)是普通的同步函数,调用它的瞬间,主线程会直接卡在这里执行它的全部逻辑(加锁、计算、释放锁),等它完全跑完返回11之后,才会轮到await do_async(2)执行。相当于两个函数是按顺序排队跑的,根本没同时干活。
那怎么改成并行呢?其实咱们可以把同步函数放到单独的线程里跑,让它和异步任务同时执行,用asyncio的工具就能轻松实现,给你改个示例代码:
import asyncio import threading def do_sync(number: int) -> int: lock = threading.Lock() lock.acquire() result = number + 10 lock.release() return result async def do_async(number: int) -> int: result = number + 10 return result async def main(): # 把同步函数丢到线程里执行,得到一个可等待的任务对象 sync_task = asyncio.to_thread(do_sync, 1) # 直接创建异步任务 async_task = do_async(2) # 同时等待两个任务完成,一次性拿到结果 sync_result, async_result = await asyncio.gather(sync_task, async_task) # 最后取最大值 result = max(sync_result, async_result) print(result) if __name__ == "__main__": asyncio.run(main())
这里的关键是asyncio.to_thread,它会把同步函数do_sync放到一个单独的线程中执行,这样主线程的事件循环就可以同时处理do_async这个异步任务,两个任务就真正并行起来了。
另外提一句:你do_sync里的锁,在当前单个调用的场景下其实没啥用,只有当多个线程同时调用这个函数、访问共享资源的时候,锁才会起到作用,不过这不影响咱们实现并行的逻辑~
备注:内容来源于stack exchange,提问作者hzk999




