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

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

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

  • 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。
  • 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。
  • 协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度。

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

协程和线程的区别是:协程避免了无意义的调度,由此可以提高性能,但也因此,程序员必须自己承担调度的责任。

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

goroutine就是一段代码,一个函数入口,以及在堆上为其分配的一个堆栈。所以它非常廉价,我们可以很轻松的创建上万个goroutine,但它们并不是被操作系统所调度执行。

和所有其他并发框架里的协程一样,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),从函数的调用者那里拷贝函数的参数,然后将控制权返回给调用者。此时,已经可以安全地调用该函数了。当函数执行完毕,事情并没有就此结束,函数的返回参数又被拷贝至调用者的栈结构中,然后释放无用的栈空间。

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

原文发布于微信公众号 - Golang语言社区(Golangweb)

原文发表时间:2016-08-01

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏北京马哥教育

【翻译】Python async/await Tutorial

原文链接: http://stackabuse.com/python-async-await-tutorial/ 过去几年,异步编程方式被越来越多的程序员使用,...

3135
来自专栏程序员的知识天地

维护Python代码的5种工具

随着软件项目进入“维护模式”,对可读性和编码标准的要求很容易落空(甚至从一开始就没有建立过那些标准)。然而,在代码库中保持一致的代码风格和测试标准能够显著减轻维...

2562
来自专栏有趣的Python

慕课网-Linux C语言编程基本原理与实践-学习笔记

个人整理,学习自用。课程内容by慕课网。 Linux C语言编程基本原理与实践 高效的学习带着目的性: 是什么 -> 干什么 -> 怎么用 重识C语言 C语言是...

3546
来自专栏xingoo, 一个梦想做发明家的程序员

图解NodeJS【基于事件、回调的单线程高性能服务器】原理

刚开始了解Node感觉很吊,各种说高性能,可是一直不理解为什么单线程会比多线程快?为什么异步IO比非阻塞IO快?因此,本篇在阅读相关书籍后,根据自己的理解,整...

2037
来自专栏猿人谷

从hello world 解析程序运行机制

开篇 学习任何一门编程语言,都会从hello world 开始。对于一门从未接触过的语言,在短时间内我们都能用这种语言写出它的hello world。 然而,对...

2176
来自专栏Java工程师日常干货

纯手写实现JDK动态代理前言JDK动态代理 手写代码实现JDK动态代理

在Java领域,动态代理应用非常广泛,特别是流行的Spring/MyBatis等框架。JDK本身是有实现动态代理技术的,不过要求被代理的类必须实现接口,不过cg...

912
来自专栏Java进阶架构师

手把手带你实现JDK动态代理

业务接口Interface、业务实现类target、业务处理类Handler、JVM在内存中生成的动态代理类$Proxy0

812
来自专栏Golang语言社区

Golang语言并发技术详解

有人把Go比作21世纪的C语言,第一是因为Go语言设计简单,第二,21世纪最重要的就是并行程序设计,而Go从语言层面就支持了并行。

5855
来自专栏FreeBuf

一个漏洞为何能影响数千万服务器以及66%安卓手机?

安全研究团队Perception Point发现Linux系统内核中存在一个高危级别的本地权限提升0day漏洞,编号为CVE-2016-0728。目前有超过66...

2115
来自专栏马洪彪

spss C# 二次开发 学习笔记(六)——Spss统计结果的输出

Spss的二次开发可以很简单,实例化一个对象,然后启用服务,接着提交命令,最后停止服务。 其中重点为提交命令,针对各种统计功能需求,以及被统计分析的数据内容等,...

3515

扫码关注云+社区

领取腾讯云代金券