当前位置: 首页 > news >正文

go语言GMP模式介绍以及协程案例展示

一. MPG模式

Go语言的调度模型被称为GMP,这是一个高效且复杂的调度系统,用于在可用的物理线程上调度goroutines(Go的轻量级线程)。GMP模型由三个主要组件构成:Goroutine、M(机器)和P(处理器)。下面详细介绍这三个组件以及它们如何协同工作。

1. Goroutine(G)

  • Goroutine 是Go语言中的一个基本概念,类似于线程,但比线程更轻量。Goroutines在Go的运行时环境中被调度和管理,而非操作系统。
  • Goroutines非常轻量,启动快,且切换开销小。这是因为它们有自己的栈,这个栈可以根据需要动态增长和缩减。

2. Machine(M)

  • M 代表了真正的操作系统线程。每个M都由操作系统调度,并且拥有一个固定大小的内存栈用于执行C代码。
  • M负责执行Goroutines的代码。Go的运行时会尽量复用M,以减少线程的创建和销毁带来的开销。

3. Processor(P)

  • P 是Go运行时的一个资源,可以看作是执行Goroutines所需的上下文环境。P的数量决定了系统同时运行Goroutines的最大数量。
  • 每个P都有一个本地的运行队列,用于存放待运行的Goroutines。
  • P的数量一般设置为等于机器的逻辑处理器数量,以充分利用多核的优势。

MPG 工作方式

  • 在程序启动时,Go运行时会根据可用的核心数创建一定数量的P。
  • 每个P都会与一个M绑定在一起,这个M会从P的本地运行队列中取出一个G来执行。
  • 当Goroutine阻塞时(比如等待I/O),执行它的M会被解绑,并且该Goroutine会被移动到全局队列或者等待队列中,让其他M可以接管这个P并继续执行其他Goroutines。
  • 如果所有的M都阻塞了,运行时会创建额外的M来保证至少有一个M是非阻塞的,以继续执行Goroutines。

调度优势

  • Go调度器的设计使得成千上万的Goroutines能够在数量较少的线程(M)上高效运行,这极大地减少了上下文切换的开销。
  • Go的调度器是协作式的,这意味着Goroutines需要自己释放控制权。通常,这发生在显式的阻塞操作(如I/O操作)或者隐式的调度点(如函数调用)时。

二.互斥锁实现阶乘计算

1.代码

package mainimport ("fmt""sync"
)// 多协程计算阶乘var (myMap = make(map[int]int) // 全局变量mu    sync.Mutex          // 安全访问myMapwg    sync.WaitGroup      // 等待所有协程完成
)func main() {// 开启协程for i := 1; i <= 10; i++ {wg.Add(1)go factorial(i)}// 等待所有协程完成后再打印wg.Wait()// 遍历myMap并打印结果for i, v := range myMap {fmt.Println(i, v)}
}// 计算阶乘
func factorial(n int) {res := 1// 计算阶乘for i := 1; i <= n; i++ {res *= i}// 递延地减少WaitGroup计数器defer wg.Done()// 在修改myMap之前进行互斥锁操作mu.Lock()myMap[n] = resmu.Unlock()
}

2.MPG模型解释

Go语言的并发模型被称为MPG模型,其中:

  • M 代表机器(Machine),是对操作系统线程的抽象。
  • P 代表处理器(Processor),是对M进行调度的上下文。
  • G 代表Goroutine,是Go的轻量级线程,它在M上执行。

当一个Go程序运行时:

  1. Goroutines(G) 在**Processors(P)**上被调度。每个P都绑定到一个M(操作系统线程),但一个P可以调度多个G。
  2. 在这段代码中,当main函数启动多个goroutines时,这些G被分配到不同的P上,并且可能在不同的M上执行。
  3. 当一个G在执行阶乘计算时,如果它需要等待(例如,等待互斥锁),它会被P挂起,并且P会转而执行另一个G。
  4. 一旦所有的G都执行完毕(即wg.Wait()返回),程序进入最后阶段,遍历并打印myMap中存储的结果。

3.管道channel基本概念

创建管道
  • 使用make关键字创建管道。可以创建有缓冲的管道或无缓冲的管道。
  • 示例:ch := make(chan int) 创建一个传递整型数据的无缓冲管道。
  • 无缓冲管道:这种管道没有存储空间,因此发送操作(ch <- v)会阻塞,直到另一端有goroutine准备好接收(<-ch)。无缓冲管道确保同时只有一个数据在通道中传递,它强制发送者和接收者同步交换数据。
  • 有缓冲管道:这种管道有一个指定的容量,允许在接收者准备好接收之前存储有限数量的值。如果管道满了(即达到其容量限制),发送操作将阻塞;如果管道为空,接收操作将阻塞。有缓冲管道提供了一定程度的松耦合,允许发送者和接收者在缓冲区不满和不空的情况下独立操作。
发送和接收数据
  • 使用箭头操作符(<-)来发送和接收数据。
  • 示例:ch <- v 表示将值v发送到管道chv := <-ch 表示从管道ch接收值并赋给变量v
无缓冲与有缓冲
  • 无缓冲管道:发送操作会阻塞,直到另一端有goroutine进行接收操作。
  • 有缓冲管道:只有当缓冲区满时发送操作才会阻塞,只有当缓冲区空时接收操作才会阻塞。
使用场景
  • 同步:管道可用于不同goroutines之间的同步。
  • 数据共享:通过管道安全地在goroutines之间传递数据,防止竞争条件。
  • 流程控制:通过有缓冲管道控制处理速度和压力。
重要特性
  • 安全性:管道在内部实现了必要的同步机制,因此在多个goroutines访问时是安全的。

  • 阻塞性:无缓冲管道在发送或接收时会阻塞,直到另一端准备好。

  • 关闭管道

  • 使用close函数关闭管道。

  • 关闭管道后,不能再向管道发送数据,但仍可以接收管道中已存在的数据。

  • 尝试向已关闭的管道发送数据会引发panic。

  • 范围循环:可以使用for range循环从管道接收数据,直到管道被关闭。

注意事项
  • 死锁:如果不正确使用管道,特别是在管道操作之间没有适当的同步时,可能导致死锁。
  • 资源管理:应确保在不再需要时关闭管道,以避免内存泄漏。

4.管道channel实现阶乘计算

package mainimport ("fmt""sync"
)var (ch  = make(chan int) // FIFO 队列 first in first out 线程安全wg2 sync.WaitGroup   // 用于等待所有goroutine完成
)func main() {for i := 1; i <= 10; i++ {// 添加WaitGroup的计数wg2.Add(1)go calChannel(i)}wg2.Wait() // 等待所有goroutine完成close(ch)  // 关闭通道// 启动一个新的goroutine来打印管道中的值go func() {for v := range ch {fmt.Println(v)}}()}func calChannel(n int) {defer wg2.Done() // 在函数退出时通知WaitGroup// 通过通道计算阶乘res := 1for i := 1; i <= n; i++ {res *= i}ch <- res
}

三. interface{}类型

package mainimport "fmt"func main() {ch := make(chan interface{}, 3)ch <- 88ch <- "i am god"cat := Cat{Name: "小花猫", Age: 4}ch <- catclose(ch)// 丢弃管道中的值<-ch<-chv := <-chfmt.Printf("%T", v)fmt.Println()// 需要类型断言 ∵从管道中取出的值类型实际是interface{}类型 只有空接口类型才可以类型断言val := v.(Cat)fmt.Printf("%v", val.Name)}type Cat struct {Name stringAge  int
}

相关文章:

go语言GMP模式介绍以及协程案例展示

一. MPG模式 Go语言的调度模型被称为GMP&#xff0c;这是一个高效且复杂的调度系统&#xff0c;用于在可用的物理线程上调度goroutines&#xff08;Go的轻量级线程&#xff09;。GMP模型由三个主要组件构成&#xff1a;Goroutine、M&#xff08;机器&#xff09;和P&#xff0…...

码牛课堂首推——鸿蒙南北双向开发学习路线图标准版~

鸿蒙&#xff01;鸿蒙&#xff01;鸿蒙&#xff01; 要说2023-2024年IT圈最火爆的名词&#xff0c;一定是鸿蒙&#xff01; 2023年9月25日&#xff0c;华为发布会正式宣布2024年第一季度将推出HarmonyOS NEXT版本&#xff0c;这意味着鸿蒙原生应用开发将彻底摆脱Android手机系…...

(亲测可行)关于提高IDEA运行速度的方案

1.作者IDEA软件版本和计算机内存 Ultimate 2022.1.2版IDEA&#xff0c;计算机内存为12GB 2.修改配置以提高IDEA运行速度的误区-调高堆内存 很多文章会教调配置的内存&#xff0c;但大多是让你调高堆内存&#xff0c;比如会让你调高-Xms -Xmx &#xff0c;这两种对应的是最…...

框架基础-Maven+SpringBoot入门

框架基础 Maven基础 Maven概述 Maven是为Java项目提供项目构建和依赖管理的工具 Maven三大功能 - 项目构建构建&#xff1a;是一个将代码从开发阶段到生产阶段的一个过程&#xff1a;清理&#xff0c;编译&#xff0c;测试&#xff0c;打包&#xff0c;安装&#xff0c;部署…...

uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -投票帖子排行实现

锋哥原创的uniapp微信小程序投票系统实战&#xff1a; uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…...

用julia演示蝴蝶效应:洛伦兹吸引子

文章目录 Lorentz吸引子julia绘图关闭抗锯齿 蝴蝶效应的名字来源于蝴蝶扇动翅膀的动作&#xff0c;虽然这个动作微小&#xff0c;但可能会在数周后引起飓风等极端天气的发生。这种现象表明&#xff0c;微小的变化可能会被放大并产生非线性的结果。这个概念最早由美国气象学家爱…...

从车联网到智慧城市:智慧交通的革新之路

一、引言 1、智慧城市的概念和发展背景 智慧城市&#xff08;Smart City&#xff09;是指以信息技术为基础&#xff0c;运用信息与通信等手段&#xff0c;对城市各个核心系统各项关键数据进行感测、分析、整合和利用&#xff0c;实现对城市生活环境的感知、资源的调控&#x…...

模拟IIC通信

模拟IIC通信 IIC 模拟IIC通信底层接口时间控制(通信速度)功能实现对外接口EEPROM相关 底层接口 device是可以用来增加多个IIC设备管理的 void I2C_SET_SCL(unsigned char device, unsigned char bit_value) {bit_value ? MCU_SCL_H() : MCU_SCL_L(); }void I2C_SET_SDA(uns…...

安卓手机变iOS!

Launcher iOS 16 - 安卓手机秒变iOS Launcher iOS 16 是一款iOS启动器&#xff0c;可以将安卓手机桌面变成iOS样子&#xff0c;还有iOS的开机动画和景深效果&#xff01; 下载链接&#xff1a;【Launcher iOS 16】 ​...

Spring使用注解管理Bean

引入lib包 Spring对Bean管理的常用注解 Component组件(作用在类上) Spring中提供了Component的三个衍生注解:(功能在目前为止是一致的) Controller WEB层 Service 业务层 Repository 持久层 属性注入的注解:(使用注解注入的方式,可以不用提供set方法) Value 用于注入普…...

弟12章 网络编程

文章目录 网络协议概述 p164TCP协议与UDP协议的区别 p165TCP服务器端代码的编写 p166TCP服务器端流程 TCP客户端代码的编写 p167TCP客户端流程主机和客户端的通信流程 tcp多次通信服务器端代码 p168TCP多次通信客户端代码 p169UDP的一次双向通信 p170udp通信模型udp接收方代码u…...

【sklearn练习】模型评估

一、交叉验证 cross_val_score 的使用 1、不用交叉验证的情况&#xff1a; from __future__ import print_function from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifieriris…...

Gazebo的模型下载。

git clone zouxu634866/gazebo_modelshttps://gitee.com/zouxu6348660/gazebo_models.git&#xff0c;并完成路径配置。 &#xff08;本文提供了gitee下载&#xff0c;国外的Github下载较慢。&#xff09;...

MyBatis - DAO 接口(Mapper.xml)支持方法重载吗?

方法重载&#xff08;Method Overloading&#xff09;是指在同一个类中定义多个方法&#xff0c;它们具有相同的方法名但参数列表不同。 Dao 在 MyBatis 的 DAO 层接口中&#xff0c;是允许方法重载的。 在 DAO 层接口中&#xff0c;可以根据不同的需求和条件定义多个方法&am…...

SAP PI之Rest adapter

一&#xff0c;简介 REST风格接口是以http为传输协议&#xff0c;以xml或json或text为有效负载。下图展示了REST到XI再返回的一个过程&#xff0c;一个REST接口包含的信息有&#xff1a;服务URL、URL中带的参数、http方法(post/get/put等)、http头部、body部分的有效载荷。而X…...

推荐几个Github高星GoLang管理系统

在Web开发领域&#xff0c;Go语言&#xff08;Golang&#xff09;以其高效、简洁、高并发等特性逐渐成为许多开发者的首选语言。有许多优秀的Go语言Web后台管理系统&#xff0c;这些项目星星众多&#xff0c;提供了丰富的功能和良好的代码质量。本文将介绍一些GitHub高星的GoLa…...

生成式对抗网络GAN

Generative Adversarial Nets由伊恩古德费洛&#xff08;Ian J.Goodfellow&#xff09;等人于2014年发表在Conference on Neural Information Processing Systems (NeurIPS)上。NeurIPS是机器学习和计算神经科学领域的顶级国际学术会议之一。 1. GAN在哪些领域大放异彩 图像生…...

Python如何使用Excel文件

使用Python操作Office——EXCEL 首先介绍下office win32 com接口&#xff0c;这个是MS为自动化提供的操作接口&#xff0c;比如我们打开一个EXCEL文档&#xff0c;就可以在里面编辑VB脚本&#xff0c;实现我们自己的效果。对于这种一本万利的买卖&#xff0c;Python怎么能放过…...

前端基础:回顾es6相关知识

Author note(题记)&#xff1a; ECMAscript is international standard of javascript。 ECMA 是 js的国际标准版语言。 let and const 为什么之前用var现在需要用let&#xff0c;const呢&#xff1f; 其实就是因为规范作用域的问题。var的作用域无块级 for (var i 0; i <…...

Hive条件函数详细讲解

Hive 中的条件函数允许你在查询中基于某些条件执行逻辑操作。以下是你提到的条件函数的详细讲解,包括案例和使用注意事项: IF() 功能:根据条件返回两个表达式中的一个。语法:IF(boolean_test, value_if_true, value_if_false)案例:SELECT IF(1=1, true, false); 结果为 tr…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...