最近在项目中使用到py中的协程,记录一下:
Python 使用 asyncio 库提供协程支持
-
协程运行时:
- Python 的协程在单线程内运行,依赖事件循环调度任务。
- 由于 GIL(Global Interpreter Lock)的存在,Python 的协程无法并行执行 CPU 密集型任务,但非常适合 I/O 密集型任务。
-
栈管理:
- Python 的协程共享同一个线程栈。
- 协程切换依靠事件循环,没有独立的栈空间。
-
优缺点:
-
优点:
- 易于编写和理解异步代码,特别是在 I/O 密集型任务中。【golang的话是协程式有独立的栈空间】
- 低开销,因为无需操作系统线程的创建和上下文切换。
-
缺点:
- 不能利用多核 CPU 进行并行计算。
- 依赖于 GIL,限制了在 CPU 密集型任务中的性能。
-
-
并发模型:
- Python 协程依赖于单线程事件循环,更适合 I/O 密集型任务。
- Go 的 goroutines 可以并行运行,适合 CPU 密集型和 I/O 密集型任务。
-
栈管理:
- Python 协程共享同一个线程栈,切换依赖事件循环。
- Goroutines 有独立的栈空间,栈大小动态调整,允许创建大量并发任务。
-
执行效率:
- Python 的协程有较低的上下文切换开销,但受限于 GIL,不能并行执行 CPU 密集型任务。
- Goroutines 可以利用多核 CPU 并行执行,具有更高的并发执行能力。
-
内存和资源开销:
- Python 协程的开销相对较低,但共享栈可能带来一些复杂性。
- Goroutines 初始栈空间小,可动态增长,允许高效地处理大量并发任务。
import asyncio
async def print_numbers(name):
print(f"开始:{name}")
await asyncio.sleep(1) # 模拟异步操作
print(f"结束:{name}")
async def main():
tasks = [
print_numbers("Task 1"),
print_numbers("Task 2"),
print_numbers("Task 3"),
print_numbers("Task 4"),
print_numbers("Task 5"),
]
await asyncio.gather(*tasks)
if __name__ == "__main__":
asyncio.run(main())