谈谈python里的协程

本文探讨了Python中协程作为生成器的本质,以及它与C语言中通过makecontext和swapcontext实现的差异。着重解释了协程执行权切换与函数调用返回的逻辑相似性,并预告了后续将深入分析asyncio编程框架。
摘要由CSDN通过智能技术生成

        在python里面,协程其实没什么可讲的,它就是生成器。

        但是关于协程编程却是值得一谈。

        不知道从什么时候开始,编程领域开始流行协程编程。普遍上的定义是说协程是用户空间的线程,也叫纤程,轻量级的线程。它像线程一样,有自己的执行入口和调用栈空间,但不同于线程,它对操作系统核心是不可见的,对它的调度需要用户代码自己去实现。

       作者最早接触协程是在c语言里,它的一个典型实现是使用makecontext来为协程创建一个执行上下文,通过调用它为协程指定一个栈(堆上申请的一块内存,一般指定1Mb大小)和一个执行的入口(一个函数,就像线程的入口函数一样),然后我们通过swapcontext来启动协程,后面的上下文切换(cpu执行权切换)通过sigsetjmp/siglongjmp来实现。

        python里的协程就是生成器了,不同于c语言的实现,python里的协程不需要为它单独指定一个调用栈,而是解释器为每个线程维护唯一一个调用栈。python里的协程执行权切换是通过类似于函数的调用/返回来实现的,调用一个协程(next/send/throw)跟调用一个函数差不多,从协程yield back到它的调用者跟函数返回差不多。

        为什么在python里面协程的执行权切换被实现为类似于函数的调用返回?

        让我们来研究一下协程切换/交换这回事。coroutine a交换到coroutine b,我们以一个二元关系(coroutine a, coroutine b)来表示。任意的两个协程coroutine a和coroutine b,如果coroutine a不是由coroutine b交换而来,它可能是第一个执行的coroutine,也可能是由另一个coroutine c交换而来,我们把coroutine a交换到coroutine b定义为ENTER,如果coroutine a是由coroutine b交换而来,那么coroutine a再交换到coroutine b,我们把它定义为YIELD。那么,任意的(coroutine a, coroutine b),它要么表示coroutine a ENTER to coroutine b,要么表示coroutine a YIELD back to coroutine b。coroutine的交换还要满足一个条件(记为A),如果coroutine a ENTER to coroutine b,coroutine a恢复执行必须等coroutine b YIELD back to coroutine a。 所以ENTER/YIELD和函数的调用/返回从交换的角度看是等价的,逻辑是一样的。所以协程的上下文切换和函数的调用返回从逻辑上看是一样的。线程的上下文切换就没有这样的因果关系了,系统核心实现了一套算法去决定什么时候暂停一个线程的执行,什么时候去恢复一个线程的执行。

        满足条件A的协程的上下文切换就相当于函数的调用返回,基本上不管什么语言的协程上下文切换都满足条件A,作者还没见过不满足的,如果不满足那意味着协程的交换可以出现了一个回路,作者想象不出来什么样的逻辑需要如此实现。

        这篇短文是个纲领性的文章,以后,作者会从代码实现的角度重点分析一个协程的编程框架asyncio,敬请期待。

  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__空无一人__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值