前言
近年来, 异步编程 (async) 在技术领域愈发流行, 尤其在Web开发中表现突出. 对于Python而言, 由于其全局解释器锁 (GIL) 的存在, 异步编程的性能甚至可以媲美多线程编程.
我个人在多个项目中实践过异步编程, 虽然对协程的底层原理和实现机制尚未完全掌握, 但在应用层面已积累了不少经验.
Python中Async的实现机制
在Python中, 异步编程依赖于协程 (coroutine). 简单来说, 协程就是一个”任务”, 通过代码中显式的控制权转移, 实现不同任务之间的调度.
程序通常是按顺序执行的, 可以将当前执行的位置理解为被”运行指针”所指向的地方.
当使用await
关键字时, 实际上是将运行指针 (即控制权) 交还给一个称为”事件循环” (event loop) 的任务调度器. 事件循环根据需求将控制权分配给需要执行的任务.
Async编程的优势
传统程序是顺序执行的, 同一时刻只能执行一行代码.
多线程编程允许多行代码同时执行, 但代价是引入了资源竞争问题.
为了解决资源竞争, 开发者引入了线程锁, 但锁机制增加了维护复杂度, 甚至可能导致死锁.
异步编程和协程在保证顺序执行和线程安全的同时, 允许耗时代码让出执行权, 给其他需要执行的程序. (但这并不意味着异步编程完全安全, 下文会详细讨论. )
当然, 异步编程始终是单线程的, 无法充分利用多核性能, 因此不适合计算密集型任务.
然而, 异步编程凭借其易用性和安全性, 在Web开发和自动化领域占据了一席之地.
个人认为, 由于Python的GIL限制, 异步编程与多线程编程在性能上并无显著差异.
Async编程的常见误区
线程安全是否等同于完全安全?
异步编程是”线程不安全”的. 虽然异步编程通过虚拟化实现了顺序执行, 但当你的逻辑被控制权的转移割裂时, 其他协程可能会修改你所依赖的变量.
不过, 幸运的是, 你可以通过简单的变量来表示锁, 而不需要进行复杂的判断.
按照Async的写法就一定能实现异步吗?
并非如此. 如果代码中从未启动任何其他任务, 那么这段代码仍然是同步执行的.
- 本文链接: https://www.zh314.xyz/2025/01/01/杂谈Python异步编程/
- 版权声明: 本博客所有文章除特别声明外,均默认采用 CC BY-NC-SA 4.0 许可协议。