go语言goroutine调度
2020-05-04 12:15
567 查看
GO语言goroutine 的调度
go 语言是通过语言层面提供并发,即go语言的并发由go从代码内部开始
go func(***){***}
goroutine
goroutine 是一个与其他goroutine并发运行在同一地址空间的GO函数或方法,其本质是协程,是并行计算的核心,只需使用关键字go即可启动一个协程,且是处于异步的运行方式。
简单来说就是golang自己实现了协程并叫作Goroutine,且比协程更强大
- 一个运行的程序是由一个或多个goroutine组成
- goroutine通过通道(channel)来通信。协程通过让出或恢复操作通信。
- 通过golang调度器进行调度,协程通过程序本身调度。o
-
并发
一个cpu上能同时执行多项任务,在短时间内,cpu来回切换任务执行,有时间上的重叠,这样看起来多个任务像同时执行。
-
并行
当有多个cpu时,每个cpu同时都运行任务,互不抢占自己所在cpu的资源,同时进行。
goroutine调度模型
Go调度器内有四个重要结构:M,P,S,Sched:1. G代表一个goroutine对象,每次go调用时,都会创建一个G对象。 2. M代表内核级线程,一个M就是一个线程,goroutine就跑在M(内核级线程)之上。 3. P代表一个处理器,每一个运行的M(内核级线程)都必须绑定一个P,就像线程必须在cpu上执行一样。 它主要用来执行goroutine,它也维护了一个goroutine队列,里面存储了所有需要它执行的goroutine. 4. sched代表调度器,维护存储M(内核级线程)和G(goroutine对象)的对了及调度器的状态。需要注意的是
P的数量可以通过GOMAXPROCS()来设置,它其实也就代表了真正的并发度,即有多少个Goroutine可以同时运行(最大256)。
每一个P保存着本地G任务队列(RunQueue),同时会有一个全局G任务队列(Global RunQueue)。
每次go调用的时候
1. 创建一个G对象,加入到本地队列或者全局队列 2. 如果还有空闲的P(处理器),则创建一个M(内核级线程) 3. M(内核级线程)会启动一个底层线程,循环执行能找到的G(goroutine对象)任务 4. G(goroutine对象)任务的执行顺序是,先从本地队列找,本地没有则从全局队列找, 之后再去其它P(处理器)中找 以上的G任务执行是按照队列顺序(也就是go调用的顺序)执行的。
当线程阻塞时
1. 当一个OS线程M陷入阻塞时,P转而去运行其他M(1),M(1)可能是正被创建,或者从线程缓存中取出。 2. 当M返回时,它必须尝试取得一个P来运行Goroutine,一般情况下,它会从其他的OS线程那里拿一个P过来。 3. 如果没有拿到的话,它就把Goroutine放在Global RunQueue里,然后自己睡眠(放入线程缓存里)。 所有的P也会周期性的检查Global RunQueue并运行其中的Goroutine, 否则Global RunQueue上的Goroutine永远无法执行。
Goruntinue如何调度
1. 系统在启动的时候,会专门创建一个线程sysmon,用来监控和管理,在内部是一个循环: 2. 记录所有P的G任务计数schedtick,schedtick会在每执行一个G任务后递增 3. 如果检查到 schedtick一直没有递增,说明这个P一直在执行同一个G任务,如果超过一定的时间(10ms), 就在这个G任务的栈信息里面加一个标记 4. 当G任务在执行的时候,如果遇到非内联函数调用,就会检查一次这个标记,然后中断自己,把自己加到队 列末尾,执行下一个G 5. 如果没有遇到非内联函数(有时候正常的小函数会被优化成内联函数)调用的话,那就惨了,会一直执 行这个G任务,直到它自己结束;如果是个死循环,并且GOMAXPROCS=1的话,恭喜你,夯住了 所以Goroutine是按照抢占式调度的,一个Goroutine最多执行10ms就会换作下一个
G任务中断后的恢复
菜猿猿 原创文章 6获赞 0访问量 142 关注 私信中断的时候将寄存器里的栈信息,保存到自己的G对象里面
当再次轮到自己执行时,将自己保存的栈信息复制到寄存器里面,这样就接着上次之后运行了
相关文章推荐
- Quartz企业作业调度配置参考
- 顺序队列实现任务以此执行-任务调度系列2
- java 任务调度
- ENode 2.0 - 介绍一下关于ENode中对Command的调度设计
- Spring-Quartz 任务调度理所当然的陷阱
- 深入linux内核架构-第二章-进程管理和调度
- Pixysoft.Framework.Schedular 作业调度 开发实录
- LMT NEW PBS作业排队运算系统对批处理作业的调度
- Mysql任务调度(Event)
- Quartz.Net 调度框架配置介绍
- Sqlserver:代理作业调度的时间不准确.作业停止问题
- Quartz.NET 的任务调度管理工具
- 进程调度的概念
- Hadoop的默认调度器JobQueueTaskScheduler的一个Map Task Pending问题
- 07-爬虫的多线程调度 | 01.数据抓取 | Python
- LVS调度方式
- Android后台调度任务与省电
- JBoss Scheduler任务调度BUG之一
- COM学习笔记8_IDispatch (调度接口) 自动化
- 贪心算法之区间调度问题