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

embedded/2024/12/23 2:12:00/

        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/embedded/100578.html

相关文章

【python】pytest可选项

pytest 是 Python 中常用的测试框架&#xff0c;它提供了许多命令行可选项&#xff08;options&#xff09;来增强测试功能和控制测试流程。下面是 pytest 中一些常见的可选项及其功能的详细介绍&#xff1a; 1. 基本可选项 -v 或 --verbose: 功能&#xff1a;增加输出的详细程…

解密《黑神话:悟空》脚本

本文部分参考来自于&#xff1a;john 《黑神话&#xff1a;悟空》这游戏昨天上线了&#xff0c;我第一时间就下载玩了。玩的时候我就挺好奇他们是怎么写的程序&#xff0c;毕竟这么大的游戏项目肯定不会只用C一种语言来写。所以我解压了游戏文件&#xff0c;看看里面有…

虚拟机virtualbox linux ubuntu使用usb串口

1.卸载brltty sudo apt remove brltty brltty是一个没啥用但是会抢占ch431的软件&#xff0c;所以卸载它 2.连接上串口&#xff0c;点击连接对应的usb串口 3.查看是否连接上 sudo dmesg -T | grep tty 查看tty组的最近日志&#xff0c;如果连接成功会显示连接的时间和串口…

Swift中的类型方法:解锁静态编程的超能力

标题&#xff1a;Swift中的类型方法&#xff1a;解锁静态编程的超能力 Swift 语言以其现代化的语法和强大的功能而著称&#xff0c;其中类型方法&#xff08;Type Methods&#xff09;是 Swift 类和结构体中非常有用的一个特性。类型方法是一种静态方法&#xff0c;它属于类型…

Golang | Leetcode Golang题解之第357题统计各位数字都不同的数字个数

题目&#xff1a; 题解&#xff1a; func countNumbersWithUniqueDigits(n int) int {if n 0 {return 1}if n 1 {return 10}ans, cur : 10, 9for i : 0; i < n-1; i {cur * 9 - ians cur}return ans }

搭配使用 ESLint 和 Prettier 优化代码风格和质量

在前端开发中&#xff0c;保持一致的代码风格和高质量的代码至关重要。ESLint 和 Prettier 是两个流行的工具&#xff0c;分别用于代码质量检测和代码格式化。然而&#xff0c;如何将这两个工具搭配使用&#xff0c;使它们相辅相成&#xff0c;是许多开发者关注的问题。本文将详…

ReactRouter6快速入门教程

快速入门案例 main.ts import { createRoot } from "react-dom/client" import App from "./App.tsx" import { BrowserRouter, Route, Routes } from "react-router-dom"function Hello() {return <h2>hello页面</h2> }createRoo…

信创海光x86服务器,定义、特点及应用详解

信创海光x86服务器是中国近年来在信息技术领域努力实现自主可控的成果之一&#xff0c;旨在打破国外技术封锁和限制&#xff0c;这类服务器的核心特点基于x86架构&#xff0c;这是一种广泛应用于全球的微处理器架构&#xff0c;由英特尔公司最初设计&#xff0c;海光作为国产处…