前面讲generator是显式的协程的时候缺一个例子,如今补上多线程
def parent_generator(): print('hello') yield from sub_generator() print('world') def sub_generator(): yield 1 gen = parent_generator() gen.send(None) gen.send(None)
这里能够看出parent_generator为了在hello和world之间中断,必须显式的用yield from把控制权从本身手里转交给调用者。若是parent_generator没有使用yield,那么sub_generator里即便有yield也没法使得parent_generator的执行权转交出去。因此从视觉上能够一步了然的指导一个函数中哪些调用是产生了switch的,哪些是确定顺序执行的。有一点相似Haskell里给全部I/O操做加类型标签的味道。并发
from greenlet import greenlet def parent(): print('hello') sub() print('world') def sub(): greenlet.getcurrent().parent.switch() g = greenlet(parent) g.switch() print('here is switched from the sub generator') g.switch()
这段代码的输出是函数
hello here is switched from the sub generator world
改用greenlet以后,协程之间的跳转就变得很是随意了。好比sub里能够直接把执行权交给main,而parent彻底不知情。从视觉上来看parent的实现里彻底不能知道在sub内部发生了switch。
虽然不能和多线程相比,可是效果是相似的。对于多线程的代码,是任何一行代码均可能与其余线程并行。相似greenlet的隐式的协程,虽然不是每一行代码均可能产生switch。虽然产生switch的地方其实和用yield写是同样多,并且也是同样固定的。可是由于缺乏强制的yield,使得在不阅读被调用函数内部的实现的前提下,没法提早知道这个调用是否会产生执行权的迁移。加上协程之间有共享状态的话,必定程度上会产生相似多线程的并发读写状态的bug。线程