深入理解 Go 语言的 GMP 调度模型

news/2024/11/15 6:07:03/

        GMP 调度模型,解释起来很简单,G ( goroutine ) 代表协程,M ( machine ) 代表线程, P(processor) 代表逻辑处理器。

1. Go 语言并发编程入门

        Go 语言天然具备并发特性,基于 go 关键字就能很方便地创建一个可以并发执行的协程。什么场景下需要协程来并发执行呢?假设有这样一个服务或者接口:需要从其他三个服务获取数据(这三个服务之间没有互相依赖),处理后返回给客户端。

        这时候如何处理呢?如果使用 PHP 语言开发,只能顺序调用这些服务获取数据;如果使用的是 Java 之类的多线程语言,为了提高接口性能,通常可能会开启多个线程并发获取数据。对于 Go 语言来说,我们可以开启多个协程去并发获取数据。Go 语言实现这一需求的程序示例如下所示:

Go">package mainimport ("fmt""sync"
)func asyncWork(workId int, wg *sync.WaitGroup) {// 开始异步任务wg.Add(1)go func() {fmt.Println(fmt.Sprintf("work %d exec", workId))//异步任务结束wg.Done()}()
}func main() {// WaitGroup 用于协程并发控制wg := sync.WaitGroup{}//启动 3 个协程并发执行任务for i := 0; i < 3; i++ {asyncWork(i, &wg)}//主协程等待任务结束wg.Wait()fmt.Println("work end")
}

程序运行结果如下所示:

Go">work 2 exec
work 1 exec
work 0 exec
work end

         参考上面的代码,我们创建了 3 个子协程去并发执行任务。子协程模拟从第三方服务获取数据的功能,主协程需要等待 3 个子协程都执行结束,相当于等待其他 3 个服务返回数据。注意,这里使用 sync.WaitGroup 实现了等待功能,这需要我们在创建子协程之前调用一下函数 wg.Add(标识一个异步子协程执行结束)。主协程调用函数 wg.Wait 之后将会一直阻塞,直到所有的异步子协程执行结束,主协程才能恢复执行。 

        这里需要再强调一点,main 函数默认在主协程执行,而且一旦 main 函数执行结束,也意味着主协程执行结束,整个 Go 程序就会结束。所以如果删除了 wg.Wait() 这一行代码,你会发现子协程不一定能执行,因为子协程可能还没有被调度,Go 程序就结束了。

        还有一个问题,主协程如何获取子协程的返回数据呢?毕竟在我们的需求里,主协程是需要汇总处理 3 个子协程的返回数据的。想想最简单的方式,能不能通过在函数 asyncWork 中添加一个指针类型的输入参数作为返回值呢?当然可以。

        其实也可以通过管道实现主协程和子协程之间的数据传递,Go 语言管道的设计初衷就是实现协程间的数据传递。想象一下,管道就像一根水管,数据从管道的一端流入,从另外一端流出。基于管道改造一下上面的程序,如下所示: 

Go">package mai

http://www.ppmy.cn/news/1514294.html

相关文章

C语言新手小白详细教程:冒泡排序

&#x1f30f;个人博客主页&#xff1a;意疏-CSDN博客 希望文章能够给到初学的你一些启发&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏支持一下笔者吧&#xff5e; 阅读指南&#xff1a; 开篇说明冒泡排序简介冒泡排序代码 开篇说明 本文我们来介绍冒…

【网络编程】第十一章 数据链路层 - 以太网(MAC+MTU+ARP+MSS+RARP)

文章目录 重点链路层以太网MAC帧格式碰撞域MAC地址MAC地址和IP地址 MTU-最大传输单元MTU 对 IP 的影响MTU 对 UDP 的影响MTU 对 TCP 的影响-MSS ARP协议ARP协议的工作流程ARP请求的过程ARP应答的过程 ARP 缓存中间人攻击 RARP协议 重点 数据链路层的作用&#xff1a;两个设备 …

OAPT:用于双JPEG伪影去除的偏移感知分区的Transformer

OAPT: Offset-Aware Partition Transformer for Double JPEG Artifacts Removal https://github.com/QMoQ/OAPT 2408.11480 (arxiv.org) 基于深度学习的方法在去除单个JPEG伪影任务中表现出了显著的性能。然而&#xff0c;现有方法在处理双重JPEG图像时往往会退化&#xff0c…

【从问题中去学习k8s】k8s中的常见面试题(夯实理论基础)(十五)

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…

报表系统之Redash

Redash 是一个开源的数据可视化和仪表板工具&#xff0c;旨在帮助用户轻松地从多个数据源中提取、查询、可视化数据&#xff0c;并分享结果。它的设计目标是让数据分析变得更加便捷&#xff0c;即使是非技术用户也能通过简单的操作生成复杂的数据报告和仪表板。 核心概念和功能…

chainlit的基本概念聊天对话中的元素

文本消息是聊天机器人的组成部分&#xff0c;但我们通常希望向用户发送的不仅仅是文本&#xff0c;还包括图像、视频等。 这就是元素出现的地方。每个元素都是一段内容&#xff0c;可以附加到Message或Step 并显示在用户界面上。 chainlit支持的元素如下&#xff1a; 文本元…

vue3+elementPlus:无法清空问题,清空表单没效果

<el-form ref"formRef" :inline"true" :model"filters" class"card table-search"><el-form-item label""><el-input v-model"filters.name" placeholder"请输入居民名称" clearable /&…

C++竞赛初阶L1-13-第五单元-循环嵌套(29~30课)536: T456455 画矩形

题目内容 根据输入的四个参数&#xff1a;a,b,c,f 参数&#xff0c;画出对应的矩形。 前两个参数 a,b 为整数&#xff0c;依次代表矩形的高和宽&#xff1b; 第三个参数 c 是一个字符&#xff0c;表示用来填充的矩形符号&#xff1b; 第四个参数 f 为整数&#xff0c;0 代表…