您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Go语言

Golang调度器

时间:2020-05-05 10:12:47  来源:  作者:

GO调度器模型

GO的调度器可以充分利用多核心CPU,任何时候都有M个go协程在N个系统线程上进行调度, 这些线程在最多 GOMAXPROCS 个CPU核心上运行,这种调度模型称之为GMP模型:

  • G : 协程(goroutine)
  • M : 系统线程(machine)
  • P : 处理器(processor)

如下图,每个P都有一个本地队列存放待运行的G,另外有一个全局队列,每个M需要依附在P上运行,一个P可以对应多个M, 但是同一时间一个P上只会有一个正在运行的M。

Golang调度器

 

每轮调度只需要找一个可运行的G执行它就行,这个查找过程如下:

runtime.schedule() {
    // 1/61 的概率去全局队列找一个G来运行
    // 如果没有找到,到本地队列中找
    // 如果没有找到,
    //     尝试从其他的P中偷取G来运行
    //     如果没有,检查全局队列
    //     如果没有,检查 Net Poller
}

GO协程的状态

GO协程和线程一样有三种状态,一个协程可以处于下面三种状态中的一种: Waiting , Runnable 和 Executing 。

  • Waiting : 这种状态意味着协程被暂停运行需要等待某些事情完成才能继续运行。 比如等待一个系统调用的返回或者一个同步调用(原子或者锁操作)。这种类型的延时是性能低下的主要原因。
  • Runnable : 这种状态说明协程正在等待被运行。如果有很多协程都在等待运行,那么协程需要等待一段更长的时间, 而且每个协程被分配的运行时间也会减少。这种调度延时也是一种性能低下的原因。
  • Executing : 这种状态说明此协程被放在了M中正在执行它的指令。

调度时机

GO程序中的下列4类事件可以触发调度器执行调度任务。并不是说这些事件发生时调度器一定会执行调度,只是说此时调度器有机会执行调度:

  • 使用 go 关键字的地方, go 关键字用于创建协程。在一个新的协程被创建的时候,就会给调度器一个机会执行调度任务。
  • 垃圾回收,GC是在自己的一套协程中运行,所以在GC过程中需要被调度执行,在GC过程中调度器会优先调度需要接触堆内存的协程
  • 系统调用,在系统调用时会导致协程阻塞这个M,调度器会将此协程调度出去或者使用一个新的M来执行队列中的其他协程。
  • 同步和编排, atomic,mutex和channel操作都可能会阻塞这个协程,此时调度器可以调度一个新的协程来运行。

异步调用

大多数操作系统都支持网络轮询,例如MacOS的kqueue,linux的epoll接口。Go会利用网络轮询接口来异步处理网络请求, 当G调用网络系统调用时调度器会将此G调度出去以避免M被阻塞,然后调度队列中的其他G继续执行,因此不需要创建一个新的M,减少调度开销。

在图1中,Goroutine-1正在M上运行,此时本地队列中有3个G在等待运行,网络轮询器上是空的。

Golang调度器

 

图2中,Goroutine-1希望进行网络系统调用,此时将Goroutine-1移至网络轮询器上处理异步网络系统调用然后将Goroutine-2调度到M上继续运行。

Golang调度器

 

图3中,网络调用完成,此时Goroutine-1被放回本地队列中,当调度到Goroutine-1时,它可以继续执行接下来的指令,这里最大的好处是执行网络系统调用不需要额外的M, 网络轮询器实际是一个系统线程专门用于处理异步网络请求。

Golang调度器

 

同步调用

当G调用同步系统调用时会怎样?例如文件相关的系统调用以及使用CGO时调用C函数也是同步调用,此时M会被此G阻塞。

图4中,Goroutine-1正在M1上运行,他要执行同步系统调用,此时会阻塞M1。

Golang调度器

 

图5中,调度器可以探测出M1被Goroutine-1阻塞了,此时调度器会将M1和P分开,但是Goroutine-1还是在M1上。 然后搞一个M2继续在P上运行,此时可以调度Goroutine-2继续执行。GO会维护一个线程池只有线程池中没有M才会创建新的M,所以这种M切换是非常快的。

Golang调度器

 

图6中,Goroutine-1的同步阻塞调用完成,此时Goroutine-1会被转移到P的本地队列中待被调度执行,此时M1会被放在线程池待下次使用。

Golang调度器

 

任务窃取

任务窃取作用是平衡P之间的负载,如果某个P上的G都执行完了,此时会检查其他P上有没有可执行的G,如果有则会窃取其他P上的G来执行。

图7中,有两个P,每个P上有4个G,全局队列中也有一个G。

Golang调度器

 

图8中,P1上的G全部执行完了,但是P2和全局队列上还有G待执行。此时P1需要窃取其他G来执行,窃取规则和调度规则是一样的参考上面的 runtime.schedule 。

Golang调度器

 

图9中,根据窃取规则,P1会将P2上一半的G窃取过来执行。

Golang调度器

 

图10中,如果此时P2上的G都执行完了,并且P1的本地队列中也没有G了会怎么办?

Golang调度器

 

图11中,P2上的G都执行完,它要开始窃取任务,但是P1上也没有G了,根据窃取规则他会把全局队列上的G拿过来执行。

Golang调度器

 

参考

这篇文章基本上是翻译下面的文章,然后加了一些自己的理解。



Tags:Golang   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
golang context 很好用,就使用php实现了github地址 : https://github.com/qq1060656096/php-go-context context使用闭坑指南1. 将一个Context参数作为第一个参数传递给传入和...【详细内容】
2021-11-05  Tags: Golang  点击:(41)  评论:(0)  加入收藏
简介工作中经常有定时执行某些代码块的需求,如果是PHP代码,一般写个脚本,然后用Cron实现。Go里提供了两种定时器:Timer(到达指定时间触发且只触发一次)和 Ticker(间隔特定时间触发)...【详细内容】
2021-05-10  Tags: Golang  点击:(310)  评论:(0)  加入收藏
不管你学没学过golang,都不妨碍这个21世纪的c语言正变得越来越流行,越来越多的平台服务使用golang来构建,我们熟知的docker就是采用golang语言进行开发设计的。谷歌作为golang...【详细内容】
2021-05-10  Tags: Golang  点击:(505)  评论:(0)  加入收藏
之前用 go 写一个小工具的时候, 用到了多个协程之间的通信, 当时随手查了查, 结果查出来一大坨, 简单记录一下. golang中多个协程之间是如何进行通信及数据同步的嘞.共享变...【详细内容】
2021-02-25  Tags: Golang  点击:(423)  评论:(0)  加入收藏
12月初,我们发现了一种新的用Golang编写的蠕虫。该蠕虫延续了 Golang在2020年流行的多平台恶意软件趋势。...【详细内容】
2021-01-05  Tags: Golang  点击:(175)  评论:(0)  加入收藏
本文主要研究一下golang的zap的ReflectType sweetenFieldszap@v1.16.0/sugar.gofunc (s *SugaredLogger) sweetenFields(args []interface{}) []Field { if len(args) ==...【详细内容】
2020-12-22  Tags: Golang  点击:(64)  评论:(0)  加入收藏
Golang的匿名结构是什么?匿名结构就像普通结构一样,但是它没有名称定义,因此不能在代码的其他地方引用。Go中的结构类似于C等其他语言中的结构。它们是字段的类型化集合,用于将...【详细内容】
2020-12-17  Tags: Golang  点击:(140)  评论:(0)  加入收藏
前文《理解 Paxos》只包含伪代码,帮助了理解但又不够爽,既然现在都讲究 Talk is cheap. Show me the code.这次就把文章中的伪代码用 Go 语言实现出来,希望能帮助各位朋友更直...【详细内容】
2020-12-15  Tags: Golang  点击:(116)  评论:(0)  加入收藏
今天逛github超市时,发现一个非常不错的数据可视化库go-echarts,特分享给大家。介绍在 Golang 这门语言中,目前数据可视化的第三方库还是特别少,go-echarts的开发就是为了填补这...【详细内容】
2020-12-15  Tags: Golang  点击:(88)  评论:(0)  加入收藏
由于Golang的语言设计的原因,不管是不是愿意,每个golang开发者的几乎每一段代码都需要与error做缠斗。下面我就简单分析一下golang中的error相关。...【详细内容】
2020-12-02  Tags: Golang  点击:(86)  评论:(0)  加入收藏
▌简易百科推荐
zip 是一种常见的归档格式,本文讲解 Go 如何操作 zip。首先看看 zip 文件是如何工作的。以一个小文件为例:(类 Unix 系统下)$ cat hello.textHello!执行 zip 命令进行归档:$ zip...【详细内容】
2021-12-17  Go语言中文网    Tags:Go语言   点击:(13)  评论:(0)  加入收藏
大家好,我是 polarisxu。前段时间,Russ Cox 明确了泛型相关的事情,原计划在标准库中加入泛型相关的包,改放到 golang.org/x/exp 下。目前,Go 泛型的主要设计者 ianlancetaylor 完...【详细内容】
2021-11-30  Go语言中文网    Tags:slices 包   点击:(24)  评论:(0)  加入收藏
前言最近因为项目需要写了一段时间的 Go ,相对于 Java 来说语法简单同时又有着一些 Python 之类的语法糖,让人大呼”真香“。 但现阶段相对来说还是 Python 写的多一些,偶尔还...【详细内容】
2021-11-25  crossoverJie    Tags:Go   点击:(29)  评论:(0)  加入收藏
go-micro是基于 Go 语言用于开发的微服务的 RPC 框架,主要功能如下:服务发现,负载均衡 ,消息编码,请求/响应,Async Messaging,可插拔接口,最后这个功能牛p安装步骤安装proto...【详细内容】
2021-09-06    石老师小跟班  Tags:go-micro   点击:(197)  评论:(0)  加入收藏
GoLand 2021.2 EAP 5 现已发布。用户可以从工具箱应用程序中获得 EAP 构建,也可以从官方网站手动下载。并且从此 EAP 开始,只有拥有有效的 JetBrains 帐户才能加入该计划。手...【详细内容】
2021-06-29  IT实战联盟  今日头条  Tags:GoLand   点击:(185)  评论:(0)  加入收藏
作者:HDT3213今天给大家带来的开源项目是 Godis:一个用 Go 语言实现的 Redis 服务器。支持: 5 种数据结构(string、list、hash、set、sortedset) 自动过期(TTL) 发布订阅、地理位...【详细内容】
2021-06-18  HelloGitHub  今日头条  Tags:Go   点击:(125)  评论:(0)  加入收藏
统一规范篇合理规划目录本篇主要描述了公司内部同事都必须遵守的一些开发规矩,如统一开发空间,既使用统一的开发工具来保证代码最后的格式的统一,开发中对文件和代码长度的控制...【详细内容】
2021-05-18  1024课堂    Tags:Go语言   点击:(232)  评论:(0)  加入收藏
闭包概述 闭包不是Go语言独有的概念,在很多编程语言中都有闭包 闭包就是解决局部变量不能被外部访问的一种解决方案 是把函数当作返回值的一种应用 代码演示总体思想:在函数...【详细内容】
2021-05-14  HelloGo  今日头条  Tags:Go语言   点击:(223)  评论:(0)  加入收藏
一时想不开,想了解一下Go语言,于是安装了并体验了一下。下载1. 进入golang.google.cn 点击Download Go 2.选择对应的操作系统,点击后开始下载。 安装1. windows下执行傻瓜式安...【详细内容】
2021-05-12  程序员fearlazy  fearlazy  Tags:Go语言   点击:(236)  评论:(0)  加入收藏
1.简介channel是Go语言的一大特性,基于channel有很多值得探讨的问题,如 channel为什么是并发安全的? 同步通道和异步通道有啥区别? 通道为何会阻塞协程? 使用通道导致阻塞的协程...【详细内容】
2021-05-10  程序员麻辣烫  今日头条  Tags:Go通道   点击:(274)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条