分享
  1. 首页
  2. 文章

goroutine的一个常见问题

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

转自:http://blog.dccmx.com/2012/03/small-problem-about-goroutine/

goroutine是Go语言的标志性特性之一。配合channel,形成了Go语言处理并发的基础。但是,目前还有些小问题,或者说小不爽。就是会给你造成真并行的假象。

看下面的例子:

package main
 
import (
 "time"
 "runtime"
)
 
func main () {
 ch := make(chan int)
 
 go func(ch chan int) {
 time.Sleep(1 * 1e9)
 ch <- 1
 }(ch)
 
 go func(ch chan int) {
 for {
 select {
 case <-ch:
 println("got!!!")
 return
 default:
 println("waiting...")
 }
 }
 }(ch)
 
 time.Sleep(2 * 1e9)
}

这里,我们的意图很明显,用一个goroutine做定时器,时间到了向channel发一信号,再用一个goroutine做事,收到信号后停止,最后一行sleep是为了防止main函数退出导致其他goroutine退出(为了省代码,这里不用channel同步了)。看起来天衣无缝,很是完美,惊叹一下Go的简洁优美。但是,运行之后会发现,一直输出waiting...,永远不会退出!

为什么??

因为Go语言现在的实现还不是很成熟,默认情况下,同时只有1个goroutine在跑,而当这个goroutine阻塞的时候,才会调度到其他的goroutine去,就像协程,不过这里由Go语言运行时帮你调度。

这个例子有三个解决方法。

1.在main函数里面第一行调用runtime.GOMAXPROCS(2)函数,将同时goroutine数设为2(或者更大),这个解决方法至少在我的双核机上跑是没问题的。1秒后就输出got!!!然后结束了。

2.制造阻塞,比如在println("waiting...")后面调用time.Sleep(1 * 1e8),这样输出10个waiting...后就got了。

3.手动切换,在println("waiting...")后面调用runtime.Gosched(),手动切换goroutine,这样也能结束。

这个问题很典型,初学者经常会中招,虽然从语义上讲,原始的做法并没有错,但是由于Go运行时还不够成熟(至少Go1看来是不打算解决了,以后会取消GOMAXPROCS改为自动判断),总之,大家小心点就好。


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

本文来自:博客园

感谢作者:sevenyuan

查看原文:goroutine的一个常见问题

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

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

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏