资讯专栏INFORMATION COLUMN

【协程原理】 - Java中的协程

dongfangyiyu / 1849人阅读

摘要:很长一段时间,我都很天真的认为,特别是以为代表的库,才是协程的乐土。里是没法实现协程,更别说实现这样可以的协程的。咱真的是太井底之蛙了。不完全列表如下还有一个据作者说是最的这些协程库的实现方式都是类似的,都是通过字节码生成达到的目的。

很长一段时间,我都很天真的认为python,特别是以gevent为代表的库,才是协程的乐土。Java里是没法实现协程,更别说实现stackless python这样可以pickle的协程的。Bong!咱真的是太井底之蛙了。
Java不但可以实现协程,而且还有很多个实现版本。不完全列表如下:

PicoThreads
http://research.microsoft.com/en-us/um/people/abegel/cs262.pdf

RIFE
http://rifers.org/wiki/display/RIFE/Web%20continuations.html

Javaflow
http://commons.apache.org/sandbox/commons-javaflow/

Matthias Mann"s
http://hg.l33tlabs.org/Continuations/
http://docs.paralleluniverse.co/quasar/
http://indiespot.net/files/projects/continuationslib/

还有一个据(作者)说是最NB的kilim (https://github.com/kilim/kilim)
这些协程库的实现方式都是类似的,都是通过jvm字节码生成达到pause/resume的目的。在这篇文章中,RIFE的作者很清楚地讲明白了其实现方式:
http://www.artima.com/lejava/articles/continuations.html

  

Geert Bevin: At the byte-code level, when the method pops variables
from the stack, exactly the same operation will be performed on the
parallel stack. We just add a piece of byte code that mimics what goes
on exactly. Then, when a continuation has to be resumed, there"s a bit
of added byte-code that interacts with the state of the stack, and
puts all the variables in the correct location so that they are
present when the executing thread passes that point. At this point,
it"s as if nothing happened—execution resumed as if nothing happened.

  

The second problem is how to arrive at the point to resume a
continuation. You want to skip over code that you don"t want to
execute. That"s easily done in byte code, because you can maintain a
tableswitch in byte code that allows you to jump to a particular
location. You can create a unique label for each continuation point,
jump to that label in the switch table, and then you know exactly what
the stack for that label of variables was. You can restore that stack,
and continue executing from that point on.

kiliam的作者用代码解释得更加清楚(http://www.malhar.net/sriram/kilim/thread_of_ones_own.pdf):

// original
void a() throws Pasuable {
    x = ...
    b(); // b is pausable
    print (x);
}

经过代码增强之后是

// transformed code
void a(Fiber f) {
    switch (f.pc) { // prelude
        case 0: goto START;
        case 1: goto CALL_B}
    START:
    x = ...
    CALL_B: // pre_call
    f.down()
    b(f);
    f.up() // post-call
    switch (f.status) {
        case NOT_PAUSING_NO_STATE:
            goto RESUME
        case NOT_PAUSING_HAS_STATE:
            restore state
            goto RESUME
        case PAUSING_NO_STATE :
            capture state, return
        case PAUSING_HAS_STATE:
            return
    }
    RESUME:
    print (x);
}

因为这些框架都是以java对象的方式来存储call stack state和programe counter的,所以要做到序列化存储一个执行中的状态(continuation)一点都不困难。RIFE在其web框架就狠狠地利用了clonable的状态来实现复杂的wizard(回到任意时刻地过去重新执行之类的)。
看过了这些实现之后,我不禁觉得持久化一个continuation好像没啥了不起的,为什么会是stackless python的pypy两家的独门绝技呢?基于CPython的两个协程实现,一个greenlet一个fibers是否可以实现状态的持久化?状态持久化能不能不用更高效的serializer来实现呢?

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64140.html

相关文章

  • 协程原理】 - 为什么greenlet的状态无法被保存

    摘要:特别是最火的协程框架也无法保存状态,让人非常惋惜。但是因为栈的本身无法持久化,所以也就无法持久化。其难度在于,假设整个要持久化的调用栈全部都是内的,比如纯的。采取的是暴力地把整个栈区域拷贝到上的方式来保存其状态。 python主流的协程实现有五种: cPython的generator cPython的greenlet cPython的fibers stackless python ...

    verano 评论0 收藏0
  • 关于PHP协程与阻塞的思考

    摘要:线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度标准线程是的。以及鸟哥翻译的这篇详细文档我就以他实现的协程多任务调度为基础做一下例子说明并说一下关于我在阻塞方面所做的一些思考。 进程、线程、协程 关于进程、线程、协程,有非常详细和丰富的博客或者学习资源,我不在此做赘述,我大致在此介绍一下这几个东西。 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系...

    FullStackDeveloper 评论0 收藏0
  • PHP回顾之协程

    摘要:本文先回顾生成器,然后过渡到协程编程。其作用主要体现在三个方面数据生成生产者,通过返回数据数据消费消费者,消费传来的数据实现协程。解决回调地狱的方式主要有两种和协程。重点应当关注控制权转让的时机,以及协程的运作方式。 转载请注明文章出处: https://tlanyan.me/php-review... PHP回顾系列目录 PHP基础 web请求 cookie web响应 sess...

    Java3y 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<