golang协程

· · 2104 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

最近在使用golang做一个爬虫,涉及到多线程,golang是没有多线程的,但是有一种更轻量级能达到类似多线程的效果,协程,golang原生支持协程。
一、怎么理解协程?
协程是golang语言特性的实现,比线程更低一级的运行方式,它不属于操作系统功能,不由操作系统分配cpu、内存,而是由golang自己实现运行资源的调度使用。也正是因此执行效率要高于线程。但是协程需要主动让出控制权后供其他协程运行。
二、如何创建协程?
这里有2种方式创建:
1、使用go创建

   go sf("a")

2、使用go函数块创建

go func() {
        sf("b")
    }()

三、使用协程的问题
1、主线程执行完成后直接结束了,此时若协程未执行完成,也会直接结束,毫无征兆。
下面是个例子

func main() {
    fmt.Println("开始启动...")
    go sf("a")
    go sf("b")
}

func sf(s string) {
    for i := 0; i < 10; i++ {
        fmt.Println(s+" ->>>", i)
    }
}

运行完成之后根本不会等两个协程完成运行,主函数直接结束了,如果将代码改一下
改版1:

func main() {
    fmt.Println("开始启动...")
    go sf("a")
    go sf("b")
       time.Sleep(time.Duration(2)*time.Minute)
}

在主函数这里阻塞一下,就可以了,但是这种方式在实际开发中是不可行的,大多不能提前知道协程需要多久运行完成。
改版2:

func main() {
    fmt.Println("开始启动...")
    var wg = sync.WaitGroup{}
    wg.Add(2)
    go func() {
        sf("a")
        wg.Done()
    }()
    go func() {
        sf("b")
        wg.Done()
    }()
    wg.Wait()
}

这样运行就ok了,这里使用了golang的WaitGroup。
理解起来就是创建一个等待的组,可以动态的添加组员的数量,然后在主函数最后一行执行wg.Wait() 来阻塞检查组员是否都完成了,协程中调用wg.Done()方法进行减一操作告知当前协程完成。
这样也会带来新的问题:
1、无法精确控制协程
2、无法准确得知哪个协程完成了或未完成
3、代码过于原始(繁琐)

拿java的多线程来理解,这个WaitGroup就像一个线程池,但是池子里只有计数器,没有实际对象。在Wait()方法一直在等待WaitGroup的校验信号,当一个协程完成时使用Done()通知WaitGroup已完成,当所有协程全部通知完成了Wait()释放,这就是一个非常简单的消息模型。
在协程这块,希望golang能优化使用方式,尽可能优雅一些。
找到了一篇讲的挺到位的文章,手动传送门 https://www.cnblogs.com/liang1101/p/7285955.html


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:

查看原文:golang协程

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2104 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传