Goroutine的调度分析(一)

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

  golang这个新兴的语言,最关键的就在于goroutine,而goroutine的调度又是golang的核心。可以说,没有goroutine,那么这个语言就会毫无意义,没有发明的必要。为了能够更好的写出高质量的代码,最近学习了goroutine的调度,收获良多。写篇文章总结记录一下。

我的参考资料

Analysis of the Go runtime scheduler 一篇分析goroutine的论文,英文的,其实这篇论文写远比很多博客来的通俗易懂,值得一看。
How Goroutines Work这篇博客简略写goroutine和线程的区别,文章底部也有更进一步阅读参考的链接
goroutine与调度器图文并茂的讲了goroutine调度的算法。值得一看。

Go RUNTIME

  Go Runtime 管理着goroutine的调度以及运行时的垃圾回收,而我们今天所讨论主要是goroutine的调度。
  Go程序会被编译成机器码,因为Go提供了,goroutine、channels、垃圾回收,所以就需要一个runtime的框架来支持这些特性。Go 程序可以被看成两层,一层是用户代码,一层是runtime并且是调用一些管理goroutine, channel, 以及一些其他的高层抽象。任何系统调用都要通过runtime层来配合goroutine的调度。下图展示了go程序、Go runtime、以及操作系统之间的关系。
这里写图片描述
  runtime记录着每一个goroutine的状态,并且会在一个线程池上来调度这些goroutine。goroutine是和线程分离的但是却需要依靠线程来运行。所以,有效地在线程池上调度goroutine对go程序的运行效率就显得非常重要了。

线程和goroutine的区别

内存的消耗

  goroutine的创建是不需要的很多内存的,大约2KB栈空间而已,而一个线程一创建就要约1MB内存,一个服务器一个请求创建一个goroutine而没有任何问题,而一个请求创建一个线程则会导致OutOfMemoryError,任何语言用多线程来实现并发都会遇到这个问题。

创建与销毁的代价

  线程的创建与销毁代价是比较大的,所以往往弄一个线程池来解决这个问题。而goroutine的创建销毁都比较cheap, 当然,其实可以看成go已经实现了线程池。

切换代价

  当线程阻塞,其他的线程必须被调度过来被阻塞线程的位置,当线程切换,调度器需要保存所有的寄存器,通用寄存器、程序计数器、栈指针还有其他一些乱七八槽的寄存器,这样的切换代价是很高的,尤其是在频繁进行线程切换的情况下。
  而goroutine的切换代价就很低了,只需要保存3个寄存器:程序计数寄存器、栈指针以及DX。所以,goroutine调度的切换代价以及时间是可以忽略不计的。

goroutine是怎么执行的

  runtime管理调度着所有的goroutine,从出生到死亡。它会分配一些线程,采用多路复用的策略,来执行goroutine。在任何时候,一个线程会执行一个goroutine,如果这个goroutine阻塞了,这个goroutine就会被换出,这个线程就会执行其他的goroutine。因为goroutine是合作式的调度(这里我也不太明白),那么如果一个goroutine不停的循环就会饿死其他的在这个线程上的goroutine。在go1.2中,这个问题已经有所缓解,当进入一个函数后,runtime会不定时的激活调度器,所以一个没有内联函数的循环会被取代。

goroutine阻塞

  goroutine是轻量级的,并且以下原因中不会造成线程阻塞。

1. 网络输入
2. sleeping
3. channel 操作
4. 通过sync包的阻塞操作

即使产生上万的goroutine,如果它们是以上4种原因阻塞的,也不会造成系统资源的浪费,因为runtime会调度其他的goroutine给这些被多路复用的thread执行。
简单来说,goroutine是在线程之上的轻量级抽象,go的使用者不用解决线程的麻烦,而系统也不会感受到goroutine的存在。

线程和处理器

  尽管你不能直接控制runtime创造线程的数量,但是你可以设置系统使用的处理器的核的数量。通过设置GOMAXPROCS,你就可以增加或减少核的数量来改善你程序的性能了。

思考

  和其他语言一样,避免同时操作共享的内存是很重要的,最好的策略是用channel来实现共享,do not cmmunicate by sharing memory; instead, share memory by communicating.


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

本文来自:CSDN博客

感谢作者:mr_fogg

查看原文:Goroutine的调度分析(一)

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

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