Goroutine(协程)为什么能处理大并发?

简单来讲:协程十分轻量,能够在一个进程中执行有数以十万计的协程,依旧保持高性能。html

进程、线程、协程的关系和区别:程序员

  • 进程拥有本身独立的堆和栈,既不共享堆,亦不共享栈,进程由操做系统调度。安全

  • 线程拥有本身独立的栈和共享的堆,共享堆,不共享栈,线程亦由操做系统调度(标准线程是的)。多线程

  • 协程和线程同样共享堆,不共享栈,协程由程序员在协程的代码里显示调度。并发

堆和栈的区别请参看:http://www.cnblogs.com/ghj1976/p/3623037.html 框架

协程和线程的区别是:协程避免了无心义的调度,由此能够提升性能,但也所以,程序员必须本身承担调度的责任。函数

 

执行协程只须要极少的栈内存(大概是4~5KB),默认状况下,线程栈的大小为1MB。性能

goroutine就是一段代码,一个函数入口,以及在堆上为其分配的一个堆栈。因此它很是廉价,咱们能够很轻松的建立上万个goroutine,但它们并非被操做系统所调度执行。spa

和全部其余并发框架里的协程同样,goroutine里所谓“无锁”的优势只在单线程下有效,若是$GOMAXPROCS > 1而且协程间须要通讯,Go运行库会负责加锁保护数据,这也是为何sieve.go这样的例子在多CPU多线程时反而更慢的缘由.操作系统

 

http://my.oschina.net/Obahua/blog/144549

goroutine 的一个主要特性就是它们的消耗;建立它们的初始内存成本很低廉(与须要 1 至 8MB 内存的传统 POSIX 线程造成鲜明对比)以及根据须要动态增加和缩减占用的资源。这使得 goroutine 会从 4096 字节的初始栈内存占用开始按需增加或缩减内存占用,而无需担忧资源的耗尽。

为了实现这个目标,连接器(5l、6l 和 8l)会在每一个函数前插入一个序文,这个序文会在函数被调用以前检查判断当前的资源是否知足调用该函数的需求(备注 1)。若是不知足,则调用 runtime.morestack 来分配新的栈页面(备注 2),从函数的调用者那里拷贝函数的参数,而后将控制权返回给调用者。此时,已经能够安全地调用该函数了。当函数执行完毕,事情并无就此结束,函数的返回参数又被拷贝至调用者的栈结构中,而后释放无用的栈空间。

经过这个过程,有效地实现了栈内存的无限使用。假设你并非不断地在两个栈之间往返,通俗地讲叫栈分割,则代价是十分低廉的。

 

参考资料:

【翻译】为何 goroutine 的栈内存无穷大? 
http://my.oschina.net/Obahua/blog/144549

进程、线程和协程的理解 
http://blog.leiqin.name/2012/12/02/%E8%BF%9B%E7%A8%8B%E3%80%81%E7%BA%BF%E7%A8%8B%E5%92%8C%E5%8D%8F%E7%A8%8B%E7%9A%84%E7%90%86%E8%A7%A3.html

协程框架的堆栈大小陷阱 
http://blog.csdn.net/huyiyang2010/article/details/6104891

Coroutine及其实现 
http://www.cnblogs.com/foxmailed/archive/2014/01/08.html

goroutine背后的系统知识 
http://www.sizeofvoid.net/goroutine-under-the-hood/

相关文章
相关标签/搜索