goroutine简介

golang语言作者Rob Pike说,“Goroutine是一个与其他goroutines 并发运行在同一地址空间的Go函数或方法。一个运行的程序由一个或更多个goroutine组成。它与线程、协程、进程等不同。它是一个goroutine“

  • goroutine通过通道来通信,而协程通过让出和恢复操作来通信;
  • goroutine 通过Golang 的调度器进行调度,而协程通过程序本身调度;

简单的说就是Golang自己实现了协程并叫做goruntine(本文称Go协程),且比协程更强大。

goroutine调度原理

上面说到Go协程是通过Golang的调度器进行调度的,其中调度器的线程模型为两级线程模型。

有关两级线程模型的介绍,可以看这篇文章

我们来看下Golang实现的两级线程模型是怎样的。首先要知道这三个字母代表的含义

  • M:代表内核级的线程
  • P:全程Processor,代表运行Go协程所需要的资源(上下文环境)
  • G:代表Go协程

    我们先看下为实现调度Golang定义了这些数据结构存M,P,G
名称 作用范围 描述
全局M列表 Go的运行时 存放所有M的单向链表
全局P列表 Go的运行时 存放所有P的数组
全局G列表 Go的运行时 存放所有G的切片
调度器的空闲M列表 调度器 存放空闲M的单向链表
调度器的空闲P列表 调度器 存放空闲P的单向链表
调度器的自由G列表 调度器 存放自由G的单向链表(有两个)
调度器的可运行G队列 调度器 存放可运行G的队列
P的自由G列表 本地P 存放当前P中自由G的单向链表
P的可运行G队列 本地P 存放当前P中可运行G的队列

然后从上往下解析Go的两级线程模型图

(1)M和内核线程之间是一对一的关系,一个M在其生命周期中,只会和一个内核线程关联,所以不会出现对内核线程的频繁切换;

Golang的运行时执行系统监控和垃圾回收等任务时候会导致创建M,M空闲时不会被销毁,而是放到一个调度器的空闲M列表中,等待与P关联,M默认数量为10000

(2)P和M之间是多对多的关系,P和G之间是一对多的关系,他们的关联是易变的,由Golang的调度器完成调度;

Golang的运行时按规则调度,让P和不同的M建立或断开关联,使得P中的G能够及时获得运行时机

(3)P的数量默认为CPU总核心数,最大为256,当P没有可运行的G时候(P的可运行G队列为空),P会被放到调度器的空闲P列表中,等待M与它关联;

P有可能会被销毁,如运行时用runtime.GOMAXPROCS把P的数量从32降到16时,剩余16个会被销毁,它们原来的G会先转到调度器可运行的G队列自由G列表

(4)每个P中有可运行的G队列(如图中最下面的那行G)和自由G列表(图中未画出来),当G的代码执行完后,该G不会被销毁,而是被放到P的自由G列表调度器的自由G列表。如果程序新建了Go协程,调度器会在自由G列表中取一个G,然后把Go协程的函数赋值到G中(如果自由G列表为空,就创建一个G);

可见Golang调度器在调度时很大程度复用了M,P,G

(5)在Go程序初始化后,调度器首先进行一轮调度,此时用M去搜索可运行的G。其中我们的main函数也是一个G,找到可运行的G后就执行它;

至于怎么找可运行的G呢?答案是到处找,想尽办法找(这里只列出一部分地方)。

  • 本地P的可运行的G队列
  • 调度器的可运行的G队列
  • 其他P的可运行的G队列

(6)P的可运行G队列最大只能存放长度为256的G,当队列满后,调度器会把一半的G转到调度器的可运行G队列

系统监控

上面大概描述了关于goroutine调度的流程。现在还存在一个问题,那就是当Go协程很多(并发量大)时候,显然G是不能一直执行下去的,因为也需要把执行机会留给其他的G。此时Golang运行时的系统监控就起作用了。
一般情况,当G运行时间超过10ms后,该G就会被系统告知需要停止了,让其他G运行。(这里情况比较复杂,并不能确保每个G都能被公平执行)

以下特殊情况该G不需要停止

  • P的可运行G队列为空(没有其他G可运行)
  • 有空闲的M在寻找可运行的G(没有其他G可运行)
  • 空闲的P(还有P闲着)

总结

Golang以两级线程实现模型,自己实现goruntine和调度器,优势在于并行和非常低的资源使用。

主要体现:

  • 内存消耗方面(每个Go协程占的内存远小于线程占的内存)
  • 切换(调度)开销方面
  • 线程切换涉及模式切换(从用户态切换到内核态)

此外,Go协程执行任务完成的顺序并不都是按我们预期的那样(程序不加以控制的情况下),特别在一些耗时较长的任务中。且每个Go协程执行的时间也不是绝对公平的。

如有错误地方,还请狂喷!

转载于:https://www.cnblogs.com/FireworksEasyCool/p/11508806.html

弄懂goroutine调度原理相关推荐

  1. 5分钟弄懂语音识别技术原理

    5分钟弄懂语音识别技术原理 首先,我们知道声音实际上是一种波.常见的mp3.wmv等格式都是压缩格式,必须转成非压缩的纯波形文件来处理,比如Windows PCM文件,也就是俗称的wav文件.wav文 ...

  2. Golang 中的 Goroutine 调度原理与 Chanel 通信

    简介   在 Go 中,每一个并发的活动称为一个 Goroutine 或者 协程.当一个程序启动时,只有一个 Goroutine 来调用 main 函数,称之为 主Goroutine.新的 Gorou ...

  3. go语言之行--golang核武器goroutine调度原理、channel详解

    一.goroutine简介 goroutine是go语言中最为NB的设计,也是其魅力所在,goroutine的本质是协程,是实现并行计算的核心.goroutine使用方式非常的简单,只需使用go关键字 ...

  4. 三幅图弄懂EventBus核心原理

    前言 好多分析EventBus的文章,喜欢上来就贴源码,我看了好多次总是迷迷糊糊的,这次花时间彻底整理一下EventBus,发现EventBus核心其实就是三幅图,这三幅图涉及的是三个HashMap表 ...

  5. 20 张图彻底弄懂 HTTPS 的原理!

    前言 近年来各大公司对信息安全传输越来越重视,也逐步把网站升级到 HTTPS 了,那么大家知道 HTTPS 的原理是怎样的吗,到底是它是如何确保信息安全传输的?网上挺多介绍 HTTPS,但我发现总是或 ...

  6. 18 张图彻底弄懂 HTTPS 的原理!

    作者 | 码海  责编 | 张文 头图 | CSDN 下载自东方 IC 来源 | 码海(ID:seaofcode) 近年来各大公司对信息安全传输越来越重视,也逐步把网站升级成 HTTPS 了.那么,大 ...

  7. 一篇文章带你飞,轻松弄懂 CDN 技术原理

    概述 Internet的高速发展,给人们的工作和生活带来了极大的便利,对Internet的服务品质和访问速度要求越来越高,虽然带宽不断增加,用户数量也在不断增加,受Web服务器的负荷和传输距离等因数的 ...

  8. 性能优化:弄懂goolg glog原理,提升程序性能

    " 当弄清一个库的原理时,发现只需要一行环境变量,竟能让程序提升20倍以上性能,瞬间解决应用层瓶颈." 01 - Google glog使用 Google glog是一个实现应用程 ...

  9. 技术干货 | 一文弄懂差分隐私原理!

    随着互联网的迅猛发展,网络早已融进人们日常生活的方方面面,我们的个人隐私在互联网时代几乎已经不是秘密.在数据时代,如何保护自己的隐私呢?差分隐私又是什么?小编用一篇文章带领大家了解什么是差分隐私,背后 ...

最新文章

  1. python皮同_Python OpenCV 图像的双线性插值算法,全网最细致的算法说明_橡皮擦,一个逗趣的互联网高级网虫-CSDN博客...
  2. Python为图像添加水印(add watermark to an image)
  3. idea springboot配置外置tomcat好处
  4. @propertysource 读不到properties_在加拿大读了6年还是大学一年级,会被赶出校吗?...
  5. 线程中这么调用类_「手撕面试官」谈谈你对JDK中Executor的理解?
  6. .NET平台常用的开发组件
  7. BugKuCTF 加密 简单加密
  8. python画图中grid等于true_Python3.0科学计算学习之绘图(二)
  9. vision画流程图的软件_产品流程图的定义,作用和画法
  10. LeetCode 671. 二叉树中第二小的节点
  11. shell 分割字符串_谈一谈Shell中的贪婪匹配和非贪婪匹配
  12. 笔记——常用网站总结
  13. java ocx调用_Javascript调用OCX控件
  14. 【JavaScript】去除空格
  15. Alexa工具栏研究
  16. PSP英文学习好助手 - 移动英语通PSP版
  17. 六轴机器人直角坐标系建立_六自由度机械手的坐标建立及运动学分析
  18. Win10环境VMware开WinXP虚拟机CPU占用100%
  19. 比较计算机动画与传统动画的异同,定格动画和传统动画有什么区别?基本一样吧?...
  20. 以太坊parity2.72节点客户端部署安装

热门文章

  1. check-lxdialog.sh: line 3: $'\r': command not found
  2. 把输入字符的小写转换成大写并输出
  3. Datawhale-零基础入门NLP-新闻文本分类Task01
  4. auto.js停止所有线程_Java多线程编程基础知识 概念介绍,以及线程状态
  5. oracle 删除补全日志组_Oracle 10g 添加、删除日志组
  6. eclipse的servlet默认不执行index_MySQL之索引及执行计划分析
  7. Mongodb 账户权限配置
  8. Chapter6_Vocoder
  9. TensorFlow 2.x GPU版在conda虚拟环境下安装步骤
  10. LeetCode 1256. 加密数字(bitset)