首页 > 编程 > Python > 正文

详细解读tornado协程(coroutine)原理

2020-02-22 22:51:49
字体:
来源:转载
供稿:网友

tornado中的协程是如何工作的

协程定义

Coroutines are computer program components that generalize subroutines for nonpreemptive multitasking, by allowing multiple entry points for suspending and resuming execution at certain locations.。 —— [ 维基百科 ]

我们在平常编程中,更习惯使用的是子例程(subroutine),通俗的叫法是函数,或者过程。子例程,往往只有一个入口(函数调用,实参通过传给形参开始执行),一个出口(函数return,执行完毕,或者引发异常,将控制权转移给调用者)。但协程是子例程基础上,一种更加宽泛定义的计算机程序模块(子例程可以看做协程的特例),它可以有多个入口点,允许从一个入口点,执行到下一个入口点之前暂停,保存执行状态,等到合适的时机恢复执行状态,从下一个入口点重新开始执行,这也是协程应该具有的能力。

定义

协程代码块

一个入口点和下一个入口点(或者退出点)中的代码。

协程模块

由n个入口点代码,和n个协程代码块组成。第一个入口点通常是一个函 数入口点。其组织形式如:函数入口点->协程代码块->入口点->协程代码块…,入口点和代码块相间。

线性模块

一个同步函数的函数体是线性执行的。也就是说一个模块中的每一行代码,相继执行,一个模块在执行中,如果还没有执行完毕,不会去执行其他模块的代码。称这样的代码模块为线性模块。

一个协程模块,如果只含有单一入口点和单一协程代码块(假设这个协程代码块全是同步代码),当然这个协程模块是一个线性执行模块,但是如果含有多个入口点和多个协程代码块,那么就不是一个线性模块。那么执行一个协程模块过程实际是分散的(不同的时间段,执行不同的协程代码块,协程代码块的执行时间段,彼此不相交),但也是顺序的(后一个协程代码块在前一个协程代码块执行结束后才执行)。两个属于同一协程模块的相继协程代码块执行的中间时间间隙,可能有很多其他协程模块的协程代码片段在执行。

生成器和yield语义

谈到协程,必须要说说python语义中的生成器(generator)。

在pep255中提到了”simple generator”和”yield语句”(此时还不是”yield表达式”)的实现。一个basic idea,提供一种函数,能够返回中间结果给调用者,然后维护函数的局部状态,以便函数当离开后,也能恢复执行。

prep255中举了一个简单的例子,生成斐波那契数列:

 def fib():   a, b = 0, 1   while 1:    yield b    a, b = b, a+b

a,b初始化为0,1。当yield b被执行,1被返回给调用者。当fib恢复执行,a,变成了1,b也是1,然后将1返回给调用者,如此循环。generator是一种非常自然的编程方式,因为对于fib来说,它的功能不变,都还是不断生成下一个斐波那契数。而对于fib的调用者来说,fib像一个列表的迭代器,不断迭代,可以获取下一个斐波那契数。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表