Golang(三)Goroutine原理
前言
- 最近用到了一些 Golang 异步编程的地方,感觉 Golang 相对于其他语言(如 Java)对多线程编程的支持非常大,使用起来也非常方便。于是决定了解一下 Goroutine 的底层原理。
- Goroutine 本质是协程,是实现并行计算的核心。只需要在对应的函数前加上 Go 关键词即可异步执行:
go func() {
}()
基本概念
- 并发:一段时间内执行多个程序,即在一个 cpu 上切换着执行多项任务,宏观上是同时的,微观上是顺序执行
- 并行:同时执行多个程序,即在多个 cpu 上同时运行不同任务,不需要上下文切换执行不同任务达到宏观同时进行的效果
- 进程:进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。是具有独立功能的程序关于某个数据集合的一次运行活动。它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体
- 线程:线程是进程的一个实体,是 cpu 调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器、一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要通过共享内存,上下文切换较快,资源开销较少
- 协程:是一种用户态的轻量级线程,协程的调度完全由用户控制。线程和进程的操作是由程序触发系统接口,最后的执行者是系统;协程的操作执行者则是用户自身程序。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。Goroutine 就是一种协程
调度模型
- Goroutine 并发调度通过 GPM 模型实现,包含四个结构:M、G、P、Sched:
- M:代表内核级线程,一个 M 对应一个线程
- G:代表一个 Goroutine,包含自己的栈、程序计数器等信息
- P:指处理器,主要用途是用来执行 Goroutine,维护一个 Goroutine 队列,同时还有一个全局队列。每一个运行的 M 都必须绑定一个 P,就像线程必须在么一个 cpu 核上执行一样
- Sched:代表调度器,维护 M 和 G 的队列和状态信息
- 如上图,2 个 M,每个 M 拥有 1 个 P 和 1 个正在运行的 G。
- P 的数量可以通过 GOMAXPROCS() 设置,代表有多少个 Goroutine 可以同时运行。
调用异步
- 执行 go func() 时,会在队列尾部加入一个 Goroutine。
- 如果此时还有空闲的 P,则创建一个 M。M 会启动一个底层线程,循环执行能找到的 G 任务。
- G 任务的执行任务是:先从本地队列找,本地没有则从全局队列找。一次转移 num(G)/num(P) 个任务,再去其他 P 中获取队列一半的任务。
监视超时
- 启动一个 G 时,会专门创建一个 Sysmon,用来监视和管理。记录所有 P 的 G 任务计数 schedtick(schedtick 会在每执行一个 G 任务后递增)。
- 如果检查到 schedtick 一直没有递增,说明这个 P 一直在执行同一个 G 任务,如果超过一定时间(10ms),就在这个 G 任务的栈信息里加一个标记。
- 内联函数执行时发现标记则中断自己,把自己加到队列末尾;非内联函数则会忽视标记,一直执行到结束。
中断恢复
- 对于一个 G 任务中断后:中断时将寄存器信息保存在 G 对象里,再次执行时将栈信息复制到寄存器里,继续执行。
首次启动
- 系统启动时主线程启动,第一个 M1 就是主线程,M1 会绑定一个 P。
- main 函数作为第一个 Goroutine 执行。
- main 里其他的 Goroutine 会绑定到当前 M1 的 P1 上。
- 执行 main 里的 Goroutine 时,会创建新的 M2,新 M2 的初始 P2 本地任务队列时空的,会从 P1 取一些过来。
- 然后依此类推直到 M 数量达到限制。
参考文献
Golang(三)Goroutine原理的更多相关文章
- 谈谈Golang中goroutine的调度问题
goroutine的调度问题,同样也是我之前面试的问题,不过这个问题我当时并不是很清楚,回来以后立马查阅资料,现整理出来备忘. 有一些预备知识需要说明,就是操作系统中的线程.操作系统中的线程分为两种: ...
- [转]golang的goroutine调度机制
golang的goroutine调度机制 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 一直对goroutine的调度机制很好奇最近在看雨痕的golang源码分析基于go ...
- golang的goroutine与channel
Golang的goroutine是非抢占式的, 令人相当蛋疼! 有痛不能呻吟...只能配合channel在各goroutine之间传递信号来实现抢占式, 而这形成了golang最灵活与最具性能的核心. ...
- 机器学习之决策树三-CART原理与代码实现
决策树系列三—CART原理与代码实现 本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-further/p/9482885.html ID ...
- go语言之行--golang核武器goroutine调度原理、channel详解
一.goroutine简介 goroutine是go语言中最为NB的设计,也是其魅力所在,goroutine的本质是协程,是实现并行计算的核心.goroutine使用方式非常的简单,只需使用go关键字 ...
- Golang/Go goroutine调度器原理/实现【原】
Go语言在2016年再次拿下TIBOE年度编程语言称号,这充分证明了Go语言这几年在全世界范围内的受欢迎程度.如果要对世界范围内的gopher发起一次“你究竟喜欢Go的哪一点”的调查,我相信很多Gop ...
- Golang Context 的原理与实战
本文让我们一起来学习 golang Context 的使用和标准库中的Context的实现. golang context 包 一开始只是 Google 内部使用的一个 Golang 包,在 Gola ...
- Golang控制goroutine的启动与关闭
最近在用golang做项目的时候,使用到了goroutine.在golang中启动协程非常方便,只需要加一个go关键字: go myfunc(){ //do something }() 但是对于一些长 ...
- golang slice 切片原理
golang 中的 slice 非常强大,让数组操作非常方便高效.在开发中不定长度表示的数组全部都是 slice .但是很多同学对 slice 的模糊认识,造成认为golang中的数组是引用类型,结果 ...
随机推荐
- 一个小巧,也很nice的“小日历”--一个Android App
一个小巧也很Nice的“小日历” 背景 因为,常用日历记一些事情,Android自带的日历,如果有事情,会显示一个小点,然后点击进去后才能看到事情的具体内容,不是很方便. 所以,写了一个“小日历” 特 ...
- MySQL各类型字段可定义最大宽度
今天浏览mysql的官网文档,无意中看到如图划线部分一句话,引起了我的兴趣,所以决定做实验官方所言. 条例1.创建数据表时,所有字段定义时"宽度之和"不得超过65535字节: 条例 ...
- File类---Day28
概述 java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建.查找和删除等操作. 构造方法 1.public File(String pathname) :通过将给定的路径 ...
- Unity Ioc 依赖倒置及Untity AOP被动拦截/自动拦截
各位博友金安,首先声明这是一篇转载的博客,原文链接:https://www.cnblogs.com/scottpei/archive/2013/01/08/2851087.html 十年河东,十年河西 ...
- 实验吧——NSCTF web200
题目地址:http://ctf5.shiyanbar.com/web/web200.jpg 打开就是个自定义加密函数,只要写出相应的解密算法就行 <?php function encode($s ...
- 定时任务突然中止,告警:Thread starvation or clock leap detected
1.背景 定时任务告警信息如下: 02:38:24.112 [HikariPool-1 housekeeper] WARN com.zaxxer.hikari.pool.HikariPool - H ...
- ML-逻辑回归推导
认识 是一个经典的二元(y=0 或 y=1) 分类算法, 不是回归 输入特征还是线性回归, 输出是 [0,1] 的一个概率值, 其判别函数的形式为: \(P(y=1|x) = \frac {1}{1+ ...
- selenium 框架
结构如下: test_project|--logs|---pages |---register_page.py| |---base_page.py|---test_case |- ...
- 编写体面的UI测试
--01-- PageObject简介 PageObject是编写UI测试时的一种模式.简而言之,你可以将所有知道页面细节的部分放入到这个对象上,对于编写测试的人来说,一个PageObject代表 ...
- jupyter配置成coding神器
参考链接: [1]http://resuly.me/2017/11/03/jupyter-config-for-windows/ [2]主题更换 切换主题:jt 主题名 -T 主题种类:chester ...