专栏首页Python程序员杂谈Goroutine VS Coroutine

Goroutine VS Coroutine

前几天flisky分享了Goroutine的方面的东西,之后我忙着做git原理的分享没来得及总结,赶紧总结下,夜长梦多难免遗忘。

Goroutine这个东西其实挺好理解的,有了对tornado的理解,这个东西其实类似,只不过tornado是基于框架的ioloop,而Goroutine是基于语言的"ioloop"——这里加引号表示其实我现在不太明白具体是什么,但是可以肯定的是它在运行时提供了类似的东西,不论是用epoll实现还是select或者其他什么实现。个人理解它是在运行时提供了类似于os的进程调度机制(感谢@monnand指正),然后它的每一个Goroutine都相当于一个进程,这样才有了Goroutine抢占式的特性(目前版本还没有实现抢占式)。(如果我理解错了,欢迎指正)

上面只是一些推理,没有实际去看Go的实现,仅作参考。下面来通过两段代码来对比Python的Coroutine(协程)和Go的Goroutine。

先来看由yield实现的Coroutine:

.. code:: python

import random

def subtask():
    i = -1 
    while True:
        a = yield i
        i += 1
        print "--- come from parent ", a

c = subtask()
c.next() # 启动协程,之后下面就可以send通信了
for i in range(10):
    sub = c.send(i)
    print "come from subtask ", sub

输出结果为::

--- come from parent  0
come from subtask  0
--- come from parent  1
come from subtask  1
--- come from parent  2
come from subtask  2
--- come from parent  3
come from subtask  3
--- come from parent  4
come from subtask  4
--- come from parent  5
come from subtask  5
--- come from parent  6
come from subtask  6
--- come from parent  7
come from subtask  7
--- come from parent  8
come from subtask  8
--- come from parent  9
come from subtask  9

其中需要解释的部分我已经写了注释。这个结果很有意思,很好的反映了主协程(或者主函数)和子协程通信的过程已经执行的过程。它依然是按照正常的程序执行顺序执行,唯一不同的是,它是由两个部分相互协作执行的。带着这个结果来看下Go的实现。

Go的代码实现同样的逻辑:

.. code:: go

package main

import (
    "fmt"
)

func subtask(in chan int, out chan int) {
    i := 0
    for {
        out <- i
        fmt.Println("--- come from parent ", <-in)
        i++
    }
}

func main() {
    var in = make(chan int, 1)
    var out = make(chan int)

    for i := 0; i < 10; i++ {
        in <- i
        go subtask(in, out)
        tmp := <-out
        fmt.Println("come from subtask ", tmp)
    }
}

来看下输出的结果::

--- come from parent  0
come from subtask  0
come from subtask  1
--- come from parent  1
come from subtask  0
--- come from parent  2
come from subtask  2
--- come from parent  3
come from subtask  0
--- come from parent  4
come from subtask  1
--- come from parent  5
come from subtask  0
--- come from parent  6
come from subtask  3
--- come from parent  7
come from subtask  0
--- come from parent  8
come from subtask  1

发现哪里不同了吗?从subtask中返回的值根本就不是按照顺序来的,也就是说主进程开启了10个Goroutine,这10个Goroutine在一定程度上是并发执行的。再反过来看Python版本的实现,虽然也是两部分但两者之间是相互协调执行的,也就是parent执行到一半,然后把控制权交给subtask,然后subtask执行到一半通过yield把控制权交给parent,如此相互执行。

再来看Goroutine执行的那个结果,如果要想达到Python的那样的效果怎么做,只能是通过加锁来实现。写到这你肯定会情不自禁的像我一样:噫,这不就是多线程吗。确实类似只不过不是直接运行在cpu上的,而是运行在Go的运行时上,至于再底层使用Thread还是什么其他的实现就不需要考虑了。

同时也侧面看出了python协程的优点,那就是在这种上下文切换并且需要保持逻辑顺序的情况下,不需要通过锁来实现。

看到这里不知道各位看官是否明白,我自己还是觉得对Goroutine这块还是有点模糊,还需要之后深入研究才行。

声明下,这篇文章有很多地方不一定正确,谨慎引用。

参考资料

flisky的gist: https://gist.github.com/flisky/7313394 (Python大牛,建议follow此人)

协程的好处:http://www.zhihu.com/question/20511233

再探协程:http://xiezhenye.com/2012/08/%E5%86%8D%E6%8E%A2-goroutine.html (注意看评论)

关于协程的调度: http://www.douban.com/note/251142022/ (源码级分析)

Goroutine性能测试:http://mikespook.com/2012/01/goroutine%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • DjangoAdmin和它的小伙伴

    look http://localhost:8000/admin/book/book/54/

    the5fire
  • java使用正则表达式抓取网页内容存为txt

    前几天女友在网上看了一本电子书,想要下载下来,不过那个网站只能支持在线阅读,不提供下载,还好可以复制粘贴。

    the5fire
  • 翻译了Django1.4数据库访问优化部分

    rst生成的html5在线ppt下载:http://www.kuaipan.cn/file/id_12834302878348970.htm

    the5fire
  • SVN previous operation has not finished

    svn提交遇到恶心的问题,可能是因为上次cleanup中断后,进入死循环了。 错误如下: ? 解决方法:清空svn的队列 1.下载sqlite3.exe   ...

    hbbliyong
  • 从零开始一起学习SLAM | 点云到网格的进化

    版权声明:本文为博主原创文章,未经博主允许不得转载。违者必究。 https://blog.c...

    用户1150922
  • Data Vault 简介

    Data Vault 2.0 不仅是建模技术,也提供了一整套数据仓库项目的方法论。它能提供一套非常可行的方案来满足数据仓库项目中对于历史轨迹和审核两个方面的需求...

    用户1217611
  • 修改Windows 7 开机启动画面

    用户1456630
  • 修改Windows 7 开机启动画面

    Youngxj
  • JDK14中record实践尝鲜

    他来了他来了,不好意思, 他来晚了. 大家好, 我是小刀,前几天看到朋友圈被jdk14的GA版本刷屏了,我一直忍到现在才写,,,唉,实在是惭愧惭愧.

    微笑的小小刀
  • 何为DOI号?

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    于小勇

扫码关注云+社区

领取腾讯云代金券