Golang goroutine MPG模式浅析

2023-11-14

协程是通过使用关键字 go 调用(或执行)一个函数或者方法来实现的(也可以是匿名函数)。

 Go 语言在语言层面上支持了并发,goroutine是Go语言提供的一种用户态线程,有时我们也称之为协程。

所谓的协程,某种程度上也可以叫做轻量线程,它不由os而由应用程序创建和管理,因此使用开销较低(一般为4K)。

我们可以创建很多的goroutine,并且它们跑在同一个内核线程之上的时候,就需要一个调度器来维护这些goroutine,确保所有的goroutine都能使用cpu,并且是尽可能公平地使用cpu资源。

调度器的主要有4个重要部分,分别是M、G、P、Sched,前三个定义在runtime.h中,Sched定义在proc.c中。

  • M (work thread) 代表了系统线程OS Thread,由操作系统管理。

  • P (processor) 衔接M和G的调度上下文它负责将等待执行的G与M对接。P的数量可以通过GOMAXPROCS()来设置,它其实也就代表了真正的并发度,即有多少个goroutine可以同时运行。

  • G (goroutine) goroutine的实体,包括了调用栈,重要的调度信息,例如channel等。

在操作系统的OS Thread和编程语言的User Thread之间,实际上存在3种线程对应模型,也就是:1:1,1:N,M:N。

  • N:1      多个(N)用户线程始终在一个内核线程上跑,context上下文切换很快,但是无法真正的利用多核。
  • 1:1      一个用户线程就只在一个内核线程上跑,这时可以利用多核,但是上下文切换很慢,切换效率很低。
  • M:N      多个goroutine在多个内核线程上跑,这个可以集齐上面两者的优势,但是无疑增加了调度的难度。

M:N 综合两种方式(N:1,1:1)的优势。多个 goroutines 可以在多个 OS threads 上处理。既能快速切换上下文,也能利用多核的优势,而Go正是选择这种实现方式。

 

 

MPG是其调度模型


M可以理解为主线程,它是一个物理级别的线程。它比较耗费资源。

p可以理解为在整个执行过程当中的上下文环境。上下文环境可以简单理解为运行时候所需要的资源或者当时操作系统的一个状态。

在主线程运行的过程当中,启动了一个协程,在协程起来的时候需要有一个上下文的环境。上下文环境,就是是否cpu可分配。需要的资源和当时运行的状态。

G是协程

多个m作用在一个cpu,那么就是并发。作用在多个cpu就是并行。可以看到M可以开启多个协程,形成一个队列。

Go 语言中的goroutine是运行在多核CPU中的(通过runtime.GOMAXPROCS(1)设定CPU核数)。 实际中运行的CPU核数未必会和实际物理CPU数相吻合。

每个goroutine都会被一个特定的P(某个CPU)选定维护,而M(物理计算资源)每次挑选一个有效P,然后执行P中的goroutine。

每个P会将自己所维护的goroutine放到一个G队列中,其中就包括了goroutine堆栈信息,是否可执行信息等等。

这里创建的M1线程可能就在其他cpu上了,有点像并行。

协程可以运行在操作系统多个线程之间,也可以运行在线程之内,让你可以很小的内存占用就可以处理大量的任务。由于操作系统线程上的协程时间片,你可以使用少量的操作系统线程就能拥有任意多个提供服务的协程,而且 Go 运行时可以聪明的意识到哪些协程被阻塞了,暂时搁置它们并处理其他协程。

 

 

总结:


M代表主线程向下执行,p上下文可以根据系统情况开启协程去工作。M可能有很多,可能全部在一个CPU上面,也可能每个M都在各个不同的CPU上面,这样就叫做并行。

当有协程被阻塞的时候,它有来回切换的一种机制。可以保证主线程的执行,也能够让排队的G协程得到执行的机会。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Golang goroutine MPG模式浅析 的相关文章

  • go struct{} 空结构体的特点和作用

    空结构体的特点和作用 参考代码 package main import fmt unsafe func main empStruct 空结构体的实例和作用 func empStruct 空结构体的特点 1 不占用内存 2 地址不变 var
  • golang-bufio 缓冲扫描

    前面两篇博客 介绍了 bufio 包中的缓冲读和写 bufio go 下面再来介绍一下缓冲扫描 scan go 这个扫描的是用来对缓存读的更高级封装 提供了一些更易用的方法 缓冲扫描 Scanner 提供了一个方便的接口来读取数据 例如使用
  • 【Golang入门】Golang第一天心得

    生活所迫 入门一下Go 很奇葩的第一点 接口 package main import fmt 定义一个接口 type Shape interface Area float64 定义一个矩形类型 type Rectangle struct W
  • 七. go 常见数据结构实现原理之 反射

    目录 一 golang 是如何实现反射的 如何比较两个对象完全相等 一 golang 是如何实现反射的 参考博客Go 语言问题集 Go Questions Go 语言在 reflect 包里定义了各种类型 实现了反射的各种函数 通过它们可以
  • go Cobra命令行工具入门

    简介 Github https github com spf13 cobra Star 26 5K Cobra是一个用Go语言实现的命令行工具 并且现在正在被很多项目使用 例如 Kubernetes Hugo和Github CLI等 通过使
  • Golang-使用 goroutine 运行闭包的“坑”

    介绍 在 Go 语言中 函数支持匿名函数 闭包就是一种特殊的匿名函数 它可以用于访问函数体外部的变量 需要注意的是 在 for range 中 使用 goroutine 执行闭包时 经常会掉 坑 因为匿名函数可以访问函数体外部的变量 而 f
  • golang sleep

    golang的休眠可以使用time包中的sleep 函数原型为 func Sleep d Duration 其中的Duration定义为 type Duration int64 Duration的单位为 nanosecond 为了便于使用
  • Go切片排序

    Go 语言标准库提供了sort包 用于对切片和用户定义的集合进行排序 具体示例如下 基本排序 package main import fmt sort func main float 从小到大排序 f float64 5 2 1 3 0 7
  • golang:环境变量GOPROXY和GO111MODULE设置

    我们安装完golang后 我们在windows的cmd命令下就可以直接查看和使用go命令和环境变量了 同样的在linux下可以在控制台使用 如下图所示 C Users lijie1 gt go env set GO111MODULE set
  • go 进阶 go-zero相关: 七. 拦截器与熔断拦截器

    目录 一 拦截器的基础使用 1 服务端拦截器 2 客户端拦截器 二 拦截器底层底层执行原理 三 go zero默认添加的拦截器 客户端 1 熔断器拦截器 BreakerInterceptor 服务端 一 拦截器的基础使用 在go zero
  • 【golang】error parsing regexp: invalid or unsupported Perl syntax (正则表达式校验密码)

    要在 Go 中编写密码校验规则 确保密码不少于8位且包含数字和字母 你可以使用正则表达式和 Go 的 regexp 包来实现 以下是一个示例代码 错误示范 package main import fmt regexp func valida
  • Go中 Redis Client的使用

    文章目录 常见操作 List 操作 Pipeline 使用 在 Go 语言中使用 Redis 时 可以使用第三方库实现 Redis Client 的封装 本文介绍如何使用 Go 语言的 redisClient 去连接 Redis 服务器 并
  • Go_接口、多态、接口继承、空接口、类型断言

    接口 接口是把所有具有共性的方法定义在一起 是方法集 任何类型实现了接口中所有的方法 就是实现了这个接口 接口可以实现多态 接口传递的是地址值 接口定义及调用 定义格式 tepe 接口名 interface 方法名 参数 返回值 调用格式1
  • Golang三剑客之Pflag、Viper、Cobra

    如何构建应用框架 想知道如何构建应用框架 首先你要明白 一个应用框架包含哪些部分 在我看来 一个应用框架需要包含以下 3 个部分 命令行参数解析 主要用来解析命令行参数 这些命令行参数可以影响命令的运行效果 配置文件解析 一个大型应用 通常
  • 基于Go语言实现简易Web应用

    目录 前言 Go语言特点 写在使用Go语言实现Web应用前面 创建Web服务器 声明一个结构体操作 加入中间件的使用 使用静态文件服务器 最后 前言 在编程语言中 近几年问世的几个新语言都是非常不错的 比如Go Python Rust等等
  • 掌握 Go 语言中的循环结构:从基础到高级

    一 if else 分支结构 1 if 条件判断基本写法 package main import fmt func main score 65 if score gt 90 fmt Println A else if score gt 75
  • GoLong的学习之路,进阶,Viper(yaml等配置文件的管理)

    本来有今天是继续接着上一章写微服务的 但是这几天有朋友说 再写Web框架的时候 遇到一个问题 就是很多的中间件 redis 微信 mysql mq 的配置信息写的太杂了 很不好管理 希望我能写一篇有管理配置文件的 所以这篇就放到今天写吧 微
  • 协程-单线程内的异步执行

    1 仿协程实例 不同事件依次顺序执行 coding utf 8 import time def calculate 1 step event name for index in range step print This is s even
  • Golang拼接字符串性能对比

    g o l a n g golang g o l an g
  • [每周一更]-(第55期):Go的interface

    参考地址 https juejin cn post 6978322067775029261 https gobyexample com interfaces https go dev tour methods 9 介绍下Go的interfa

随机推荐

  • 大屏数据可视化——屏幕适配方案(多分辨率下)

    文章目录 前言 一 一些前提概念 1 1 常见大屏分辨率 1 2 设备像素 二 适配痛点 三 关于rem 四 关于px2rem 五 适配方案 5 1 rem自适应缩放 5 2 css3缩放scale 六 demo演示 6 1 1366 76
  • vs2017统计代码行数方法

    方法一 查找所有代码行数 包括系统生成 1 打开项目 2 编辑 查找和替换 选中 在文件中查找 然后就会弹出一个查找框 输入正则表达式 b b 选择查找整个解决方案 查找选项选择使用正则表达式 然后查找全部 最后就会统计出一共有几行 方法二
  • 华为OD机试 Java查找人名

    题目 代码 import java util ArrayList import java util List public class NameMatcher public
  • 网速dns怎么调快_Switch【实用DNS分享】:有效提升网络速度!

    最近很多朋友反应 似乎又有一批DNS不太灵了 下载速度直线下降 游戏联网体验也大打折扣 根据检测以下是出问题的DNS和一批没被 污染 的DNS 测试网络环境 广东电信 100M光纤 被淘汰的DNS 如果还有使用这一批DNS的玩家请研究一下自
  • BeanUtils.copyProperties的使用方法

    BeanUtils copyProperties的使用方法 1 使用的是springframe包下的 BeanUtils copyProperties a b 把a属性拷贝给b属性 2 注意事项 使用时 例如 a和b都用page封装起来 P
  • STM32F103 内部FLASH读写擦操作

    内部flash介绍 开发步骤 1 解锁和锁定 前面我们介绍了在对 FLASH 进行写操作前必须先解锁 解锁操作也就是必 须在 FLASH KEYR 寄存器写入特定的序列 0X45670123 和 0XCDEF89AB 固件库 提供了一个解锁
  • nginx(六十七)http_ssl模块 client与nginx的ssl握手

    一 HTTPS握手机制 关注点 SSL TLS握手 的细节与nginx 配置指令 的关系 核心 讲解 客户端 下游 与作为 server 端的nginx之间的 握手 最佳实践 建议在 http块 中通过 include ssl conf 把
  • 01-pytest-安装及入门

    目录 1 安装 2 查看版本 3 创建第一个测试 4 pytest用例规则 1 安装 pip install U pytest 2 查看版本 pytest version 或 pip show pytest 3 创建第一个测试 1 新建te
  • 分享一个QTabWidget的好看样式

    void setTabWidgetStyleSheet QTabWidget obj obj gt setStyleSheet QTabWidget background color transparent QTabWidget pane
  • python rfind函数用法_纵经千万次增删改,初心永不变

    开篇 上一期介绍了字符串及其切片用法 相信你已经掌握 那么这一期 我们就来学习一下字符串的增删改查等一系列方法 正是因为有了这些方法 你才能像呼吸一样自然地操作字符串 需要指出的是 字符串是不可变类型 也就是说 只要一个字符串确定了 那么任
  • Navicat远程连接mysql数据库

    第一 首先能ping通mysql数据库所在的主机 第二 telnet mysql数据库的端口号 如果不行 要在防火墙 高级设置里面 配置入站规则 开放3306端口 第三 如果还不行 结合下面两个网址 http blog csdn net a
  • iOS进阶_Log分类打印日志自动转换中文

    description方法是NSObject类的一个实例方法 因此所有的Object C对象都有description方法 description方法返回的永远是字符串 对于一个Person类 如果没有重写description方法 NSL
  • DWR3常见错误解决方法

    1 提示 缺少对象 原因 程序中使用了dwr util setValue userInfo data 或getValues 之类的语句 而控件ID与这里的userInfo名字不匹配 则提示缺少对象 解决方法 检查每一个setValue中的控
  • 设置对象的键为一个变量

    在JS中将对象的键设为变量的方法是将对象的键用 包起来 否则会直接识别成键名 例如 var key mykey var num mynum let obj key num 上面代码创建后的对象是 key mynum 并不是我们所期望的 my
  • (CVPR2019医学影像)LesaNet配置

    目录 一 环境配置 1 下载CADLab中的LesaNet文件夹 2 roi pooling编译 3 预训练模型下载 二 数据集 三 配置参数 1 demo 2 训练 3 测试 作者原版github LesaNet 一 环境配置 1 下载C
  • 【STM32】系统时钟RCC详解(超详细,超全面)

    转载 https blog csdn net as480133937 article details 98845509 1什么是时钟 时钟是单片机运行的基础 时钟信号推动单片机内各个部分执行相应的指令 时钟系统就是CPU的脉搏 决定cpu速
  • 嵌入式毕业设计 基于红外热释电的房间人数计数系统 - 单片机 物联网嵌入式

    文章目录 0 前言 1 简介 2 主要器件 3 实现效果 4 设计原理 4 1 PIR传感器 4 2 mlx90614红外传感器 5 部分核心代码 6 最后 0 前言 这两年开始毕业设计和毕业答辩的要求和难度不断提升 传统的毕设题目缺少创新
  • 谈谈前后端分离

    1 首先我们先看看SPA SPA全称是single page application 单页面应用 它是一种网络应用程序 webAPP 模型 传统网站里面 不同页面的切换一般是直接从服务器加载一整个新页面 而SPA这个模型 则是通过动态的重写
  • AI根据视频画面自动配音 ,真假难辨 !(附数据集)

    本文经AI新媒体量子位 公众号ID qbitai 授权转载 转载请联系出处 本文长度为3216字 建议阅读7分钟 本文为你分享实现AI自动为视频配音的流程 先来做个 真假美猴王 的游戏 你将看到两段画面相同的视频 请判断哪段来自视频原声 哪
  • Golang goroutine MPG模式浅析

    协程是通过使用关键字 go 调用 或执行 一个函数或者方法来实现的 也可以是匿名函数 Go 语言在语言层面上支持了并发 goroutine是Go语言提供的一种用户态线程 有时我们也称之为协程 所谓的协程 某种程度上也可以叫做轻量线程 它不由