java greenlet_【generator101】 - 对比generator和greenlet

前面讲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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值