Coroutine-协程

协程(Coroutine)是 Python 中一种用户态的并发机制,本质是可以“暂停和恢复执行”的函数。

为什么需要协程呢?

模型问题
同步阻塞
线程开销大 / 锁
协程✅ 解决 I/O 并发

协程的目标是:用单线程实现高并发 I/O 密集型任务


其实我刚开始的时候,学习这里没有搞懂,其实我们看一段代码就知道了:

我们需要知道一点,就是一切用async def 定义的function 都是 Coroutine function,直接调用Coroutine funcion 的话,和generator一样,不会执行这个function里面的代码,而是会返回一个Coroutine对象。

那么我们就会想,如何去运行我们的Coroutine代码呢?一共有三种标准方式


在分析之前,我们还得介绍一下 什么叫Event Loop:

Event Loop(事件循环)是一个不断循环的调度器,负责管理和切换多个协程(Task)的执行。 这是有点官方的话了,但是我们可以把他理解为一个大脑,它现在面对很多任务,他负责管理和切换多个coroutine。


我们来分析一下这段代码的执行流程:

当我们运行asyncio.run(main())的时候,创建了一个 Event Loop ,并把 main() 这个Coroutine对象 包装成一个task,并注册到这个 Event Loop里面, 现在Event Loop一看里面的任务,只有一个main,那么就会执行这个main任务,当main任务执行到 task1的那个create_task()这一行的时候,会创建一个新的 coroutine: say_after(1, 'hello') ,并将这个coroutine 包装成一个Task(task1) ,把这个task1 注册到 Event Loop中,然后告诉 Event Loop说,task1 已经可以开始执行了,但是Event Loop现在没有办法执行,因为控制权还在main手里,那么main 现在趁着手上还有控制权,赶紧做了第二个create_task这个task2,同样也是告诉main,这里还有个新的task哦,叫作[say_after(2,'world')],也可以开始运行了,在这里之后,他才开始进行await task1await task2, 那么main遇到await task1 的时候,就会告诉 Event Loop, 我现在需要等task1 完成了,我才能接着执行,所以把控制权又给了Event Loop,Event Loop就会去执行task1,task1 跟 Event Loop说,我需要一秒才能执行完毕,Event Loop 闲来无事就发现,这里有一个task2可以执行,于是他就执行了task2, task2 跟他说,我需要两秒才能完成,这样两个task就可以同时进行等待了。

以上就是大概的执行流程,毕竟这个写的有点绕,有点糊涂了可能。。。


总结就是:协程不会被强制打断,只有在 await 时才会主动让出控制权,这种机制称为“协作式调度”。

协程的本质是:通过 await 主动让出执行权,由事件循环调度,从而在单线程中实现高并发 I/O。