从调度上看,goroutine的调度开销远远小于线程调度开销。

OS的线程由OS内核调度,每隔几毫秒,一个硬件时钟中断发到CPU,CPU调用一个调度器内核函数。这个函数暂停当前正在运行的线程,把他的寄存器信息保存到内存中,查看线程列表并决定接下来运行哪一个线程,再从内存中恢复线程的注册表信息,最后继续执行选中的线程。这种线程切换需要一个完整的上下文切换:即保存一个线程的状态到内存,再恢复另外一个线程的状态,最后更新调度器的数据结构。某种意义上,这种操作还是很慢的。

Go运行的时候包涵一个自己的调度器,这个调度器使用一个称为一个M:N调度技术,m个goroutine到n个os线程(可以用GOMAXPROCS来控制n的数量),Go的调度器不是由硬件时钟来定期触发的,而是由特定的go语言结构来触发的,他不需要切换到内核语境,所以调度一个goroutine比调度一个线程的成本低很多。

从栈空间上,goroutine的栈空间更加动态灵活。

每个OS的线程都有一个固定大小的栈内存,通常是2MB,栈内存用于保存在其他函数调用期间哪些正在执行或者临时暂停的函数的局部变量。这个固定的栈大小,如果对于goroutine来说,可能是一种巨大的浪费。作为对比goroutine在生命周期开始只有一个很小的栈,典型情况是2KB, 在go程序中,一次创建十万左右的goroutine也不罕见(2KB*100,000=200MB)。而且goroutine的栈不是固定大小,它可以按需增大和缩小,最大限制可以到1GB。

goroutine没有一个特定的标识。

在大部分支持多线程的操作系统和编程语言中,线程有一个独特的标识,通常是一个整数或者指针,这个特性可以让我们构建一个线程的局部存储,本质是一个全局的map,以线程的标识作为键,这样每个线程可以独立使用这个map存储和获取值,不受其他线程干扰。

goroutine中没有可供程序员访问的标识,原因是一种纯函数的理念,不希望滥用线程局部存储导致一个不健康的超距作用,即函数的行为不仅取决于它的参数,还取决于运行它的线程标识。

reference: 《Go程序设计语言》

最新文章

  1. H3 BPM初次安装常见错误详解1-4
  2. 【webapp的优化整理】要做移动前端优化的朋友进来看看吧
  3. Bootstrap<基础十五> 输入框组
  4. 2013 Visual Studio Magazine读者选择奖界面框架类获奖情况
  5. LINQ to Entities 和LINQ to Objects 的区别
  6. JAVA算术运算符、关系运算符和位运算符
  7. strcpy(),string使用问题
  8. Ubuntu pip 安装网络爬虫框架 scrapy 出现的错误
  9. ExecuteReader(),ExecuteNonQuery(),ExecuteScalar(),ExecuteXmlReader()之间的区别
  10. android小知识之多个listview在同一界面只有item高亮
  11. BestCoder Round #11 (Div. 2) 题解
  12. JAVA中用于处理字符串的“三兄弟”
  13. Spring_Spring与AOP_AspectJ基于注解的AOP实现
  14. 【编程练习】poj1111
  15. Android研发进阶之路
  16. WiFi其他方法和WiFi事件响
  17. 查询最新记录的sql语句效率对比
  18. Codeforces.618F.Double Knapsack(构造 鸽巢原理)
  19. Universal-Image-Loader源码分析(二)——载入图片的过程分析
  20. 记录:Ubuntu 18.04 安装 tensorflow-gpu 版本

热门文章

  1. E-JSON数据传输标准
  2. Git添加文件改动时出错
  3. LoadRunner压力测试实例
  4. PLSQL WEBSERVICES 发布
  5. 【一天一道LeetCode】 #1 Two Sum
  6. Android开发概要记录
  7. OpenCV——PS 滤镜, 浮雕效果
  8. 拆轮子之Fish动画分析
  9. 超强js博客值得学习!!!
  10. 10.API 接口自动化测试的基本原理