【Golang 面试 - 进阶题】每日 3 题(十四)

✍个人博客:Pandaconda-CSDN博客

📣专栏地址:http://t.csdnimg.cn/UWz06

📚专栏简介:在这个专栏中,我将会分享 Golang 面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

40. 基 于信号的抢占式调度

在 golang 中,除了协作式调度和抢占式调度,还有一种基于信号的抢占式调度。基于信号的抢占式调度可以让 Goroutine 在执行过程中被立即中断,并强制切换到其他 Goroutine,从而实现抢占式调度。

在 golang 中,我们可以使用 runtime 包中的两个函数实现基于信号的抢占式调度:

  • runtime.Gosched():让出 CPU 时间片,让其他 Goroutine 运行。

  • runtime.LockOSThread():将当前 Goroutine 绑定到当前线程上,让该 Goroutine 独占一个线程,从而实现更精细的调度控制。

下面是一个简单的基于信号的抢占式调度的示例代码:

package main
import ("fmt""runtime""time"
)
func main() {go func() {for {fmt.Println("Goroutine 1 is running")runtime.Gosched()}}()go func() {for {fmt.Println("Goroutine 2 is running")runtime.Gosched()}}()for {fmt.Println("Main Goroutine is running")time.Sleep(time.Second)}
}

在这个示例代码中,我们定义了三个 Goroutine,分别是“Goroutine 1”、“Goroutine 2”和“Main Goroutine”。其中,“Goroutine 1”和“Goroutine 2”分别不断输出自己的名称,并在每次输出后使用 runtime.Gosched() 函数让出 CPU 时间片,从而实现抢占式调度。而“Main Goroutine”每秒输出一次自己的名称,并使用 time.Sleep() 函数暂停一秒钟,从而实现协作式调度。

需要注意的是,基于信号的抢占式调度不适用于所有场景,因为频繁调用 runtime.Gosched() 函数会导致性能下降,应该根据实际需求进行选择。

41. Go 如何查 看运行时调度信息?

有 2 种方式可以查看一个程序的调度 GMP 信息,分别是 go tool trace 和 GODEBUG。

trace.go

package main
import ("fmt""os""runtime/trace""time"
)
func main() {//创建trace文件f, err := os.Create("trace.out")if err != nil {panic(err)}defer f.Close()//启动trace goroutineerr = trace.Start(f)if err != nil {panic(err)}defer trace.Stop()//mainfor i := 0; i < 5; i++ {time.Sleep(time.Second)fmt.Println("Hello World")}
}

go tool trace

启动可视化界面:

go run trace.go
go tool trace trace.out
2022/04/22 10:44:11 Parsing trace...
2022/04/22 10:44:11 Splitting trace...
2022/04/22 10:44:11 Opening browser. Trace viewer is listening on http://127.0.0.1:35488

打开 http://127.0.0.1:35488 查看可视化界面:

  

点击 view trace 能够看见可视化的调度流程:

  

一共有 2 个 G 在程序中,一个是特殊的 G0,是每个 M 必须有的一个初始化的 G,另外一个是 G1 main goroutine (执行 main 函数的协程),在一段时间内处于可运行和运行的状态。

1. 点击 Thr eads 那一行可视化的数据条,我们会看到 M 详细的信息

  

一共有 2 个 M 在程序中,一个是特殊的 M0,用于初始化使用,另外一个是用于执行 G1 的 M1。

2. 点击 Proc  那一行可视化的数据条,我们会看到 P 上正在运行 goroutine 详细的信息

一共有 3 个 P 在程序中,分别是 P0、P1、P2。

  

点击具体的 Goroutine 行为后可以看到其相关联的详细信息:

Start:开始时间
Wall Duration:持续时间
Self Time:执行时间
Start Stack Trace:开始时的堆栈信息
End Stack Trace:结束时的堆栈信息
Incoming flow:输入流
Outgoing flow:输出流
Preceding events:之前的事件
Following events:之后的事件
All connected:所有连接的事件

GODEBUG

GODEBUG 变量可以控制运行时内的调试变量。查看调度器信息,将会使用如下两个参数:

  • schedtrace:设置 schedtrace=X 参数可以使运行时在每 X 毫秒发出一行调度器的摘要信息到标准 err 输出中。

  • scheddetail:设置 schedtrace=Xscheddetail=1 可以使运行时在每 X 毫秒发出一次详细的多行信息,信息内容主要包括调度程序、处理器、OS 线程 和 Goroutine 的状态。

查看基本信息

go build trace.go
GODEBUG=schedtrace=1000 ./trace
SCHED 0ms: gomaxprocs=8 idleprocs=6 threads=4 spinningthreads=1 idlethreads=0 runqueue=0 [1 0 0 0 0 0 0 0]
Hello World
SCHED 1010ms: gomaxprocs=8 idleprocs=8 threads=4 spinningthreads=0 idlethreads=2 runqueue=0 [0 0 0 0 0 0 0 0]
Hello World
SCHED 2014ms: gomaxprocs=8 idleprocs=8 threads=4 spinningthreads=0 idlethreads=2 runqueue=0 [0 0 0 0 0 0 0 0]
Hello World
SCHED 3024ms: gomaxprocs=8 idleprocs=8 threads=4 spinningthreads=0 idlethreads=2 runqueue=0 [0 0 0 0 0 0 0 0]
Hello World
SCHED 4027ms: gomaxprocs=8 idleprocs=8 threads=4 spinningthreads=0 idlethreads=2 runqueue=0 [0 0 0 0 0 0 0 0]
Hello World
SCHED 5029ms: gomaxprocs=8 idleprocs=7 threads=4 spinningthreads=0 idlethreads=2 runqueue=0 [0 0 0 0 0 0 0 0]

sched:每一行都代表调度器的调试信息,后面提示的毫秒数表示启动到现在的运行时间,输出的时间间隔受 schedtrace 的值影响。

gomaxprocs:当前的 CPU 核心数(GOMAXPROCS 的当前值)。

idleprocs:空闲的处理器数量,后面的数字表示当前的空闲数量。

threads:OS 线程数量,后面的数字表示当前正在运行的线程数量。

spinningthreads:自旋状态的 OS 线程数量。

idlethreads:空闲的线程数量。

runqueue:全局队列中中的 Goroutine 数量,而后面的[0 0 0 0 0 0 0 0] 则分别代表这 8 个 P 的本地队列正在运行的 Goroutine 数量。

查看详细信息

go build trace.go
GODEBUG=scheddetail=1,schedtrace=1000 ./trace
SCHED 0ms: gomaxprocs=8 idleprocs=6 threads=4 spinningthreads=1 idlethreads=0 runqueue=0 gcwaiting=0 nmidlelocked=0 stopwait=0 sysmonwait=0P0: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=1 gfreecnt=0 timerslen=0P1: status=1 schedtick=0 syscalltick=0 m=2 runqsize=0 gfreecnt=0 timerslen=0P2: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0P3: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0P4: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0P5: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0P6: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0P7: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 timerslen=0M3: p=0 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=false blocked=false lockedg=-1M2: p=1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=2 dying=0 spinning=false blocked=false lockedg=-1M1: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=2 dying=0 spinning=false blocked=false lockedg=-1M0: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=false blocked=false lockedg=1G1: status=1(chan receive) m=-1 lockedm=0G2: status=1() m=-1 lockedm=-1G3: status=1() m=-1 lockedm=-1G4: status=4(GC scavenge wait) m=-1 lockedm=-1

G

status:G 的运行状态。
m:隶属哪一个 M。
lockedm:是否有锁定 M。

G 的运行状态共涉及如下 9 种状态:

状态含义
_Gidle0刚刚被分配,还没有进行初始化。
_Grunnable1已经在运行队列中,还没有执行用户代码。
_Grunning2不在运行队列里中,已经可以执行用户代码,此时已经分配了 M 和 P。
_Gsyscall3正在执行系统调用,此时分配了 M。
_Gwaiting4在运行时被阻止,没有执行用户代码,也不在运行队列中,此时它正在某处阻塞等待中。
_Gmoribund_unused5尚未使用,但是在 gdb 中进行了硬编码。
_Gdead6尚未使用,这个状态可能是刚退出或是刚被初始化,此时它并没有执行用户代码,有可能有也有可能没有分配堆栈。
_Genqueue_unused7尚未使用。
_Gcopystack8正在复制堆栈,并没有执行用户代码,也不在运行队列中。

M

p:隶属哪一个 P。
curg:当前正在使用哪个 G。
runqsize:运行队列中的 G 数量。
gfreecnt:可用的G(状态为 Gdead)。
mallocing:是否正在分配内存。
throwing:是否抛出异常。
preemptoff:不等于空字符串的话,保持 curg 在这个 m 上运行。

P

status:P 的运行状态。
schedtick:P 的调度次数。
syscalltick:P 的系统调用次数。
m:隶属哪一个 M。
runqsize:运行队列中的 G 数量。
gfreecnt:可用的G(状态为 Gdead)
状态含义
_Pidle0刚刚被分配,还没有进行进行初始化。
_Prunning1当 M 与 P 绑定调用 acquirep 时,P 的状态会改变为 _Prunning。
_Psyscall2正在执行系统调用。
_Pgcstop3暂停运行,此时系统正在进行 GC,直至 GC 结束后才会转变到下一个状态阶段。
_Pdead4废弃,不再使用。

42. GMP 调度过程中存在哪些阻塞?

在 GMP(GNU 多精度算术库)调度过程中,可能会存在以下几种阻塞情况:

  1. IO 阻塞:当 GMP 库进行 IO 操作时,如果 IO 操作需要等待数据读取或写入,此时 GMP 库的调度可能会被阻塞。

  2. 系统调用阻塞:当 GMP 库使用系统调用时,如申请内存、获取时间等,如果系统调用需要等待结果返回,此时 GMP 库的调度可能会被阻塞。

  3. 锁竞争阻塞:当多个线程同时访问 GMP 库的同一个数据结构时,可能会出现锁竞争的情况,如果某个线程获得锁并持有锁的时间过长,其他线程的调度可能会被阻塞。

  4. 垃圾回收阻塞:在 GMP 库中,存在一种称为 “垃圾回收” 的机制,用于释放不再使用的内存。当垃圾回收机制启动时,所有线程的调度都会被暂停,直到垃圾回收完成。

总之,GMP 调度过程中的阻塞情况可能会导致程序执行时间延长,因此在编写 GMP 应用程序时需要考虑如何避免或减少阻塞情况的发生。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/391472.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python pip怎么安装包

按WinR键打开运行窗口&#xff0c;输入“cmd”&#xff0c;再按回车键&#xff0c;打开命令行窗口。 找到pip安装路径。 Python2/Python3安装路径是相同的&#xff0c;都在x:\Python xx\Scripts路径下。 拖动pip主应用程序到命令行窗口。 输入“install 模块/包名”&#xff…

【Golang 面试 - 进阶题】每日 3 题(十)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

PCIe总线-RK3588 PCIe RC初始化流程分析(十二)

1.简介 RK3588 PCIe RC的初始化涉及PCIe设备枚举、中断&#xff08;INTx、MSI、MSI-X&#xff09;配置、BAR配置、ATU配置、链路训练等&#xff0c;下面一一介绍。 2.初始化 当RC的模式为RK_PCIE_EP_TYPE时&#xff0c;平台驱动调用rk_add_pcie_port函数初始化RC&#xff0c…

【论文笔记】4D Millimeter-Wave Radar in Autonomous Driving: A Survey

原文链接&#xff1a;https://arxiv.org/abs/2306.04242 I. 引言 传统毫米波雷达&#xff08;3D毫米波雷达&#xff09;测量俯仰角的能力有限&#xff0c;数据通常仅包括距离、水平角和多普勒速度信息。此外&#xff0c;3D雷达数据存在噪声且分辨率低&#xff08;尤其是水平角…

python学习之路 - python的函数

目录 一、python函数1、函数介绍2、函数的定义3、函数的参数4、函数的返回值5、函数说明文档6、函数的嵌套调用7、变量的作用域8、综合案例9、函数与方法的区别 二、python函数进阶1、函数多返回值2、函数多种传参方式a、位置参数b、关键字参数c、缺省参数d、不定长参数 3、匿名…

【2024年华数杯C题老外游中国】(完整题解+代码+完整参考论文)

请问 352 个城市中所有 35200 个景点评分的最高分&#xff08;Best Score&#xff0c;简称 BS&#xff09;是多少&#xff1f;全国有多少个景点获评了这个最高评分&#xff08;BS&#xff09;&#xff1f;获评了这个最高评分&#xff08;BS&#xff09;景点最多的城市有哪些&am…

代码坏味道有24种?我看未必

微信公众号&#xff1a;牛奶 Yoka 的小屋 有任何问题。欢迎来撩~ 最近更新&#xff1a;2024/08/03 [大家好&#xff0c;我是牛奶。] 我在上一篇文章打开IDEA&#xff0c;程序员思考的永远只有两件事&#xff01;中&#xff0c;通过代码命名、重复代码、合格方法三个章节&#…

请你学习:前端布局3 - 浮动 float

1 标准流&#xff08;也称为普通流、文档流&#xff09; 标准流&#xff08;也称为普通流、文档流&#xff09;是CSS中元素布局的基础方式&#xff0c;它决定了元素在页面上的默认排列方式。这种布局方式遵循HTML文档的结构&#xff0c;不需要额外的CSS样式来指定元素的位置。…

MongoDB未授权访问漏洞

MongoDB未授权访问漏洞 mongodb数据库是由C编写&#xff0c;主要是为了提供web应可用扩展的一种高性能数据库。开启MongoDB服务时不添加任何参数时,默认是没有权限验证的,登录的用户可以通过默认端口无需密码对数据库任意操作(增、删、改、查高危动作)而且可以远程访问数据库。…

MySQL数据库学习笔记

1、数据库的相关概念 数据库是存储数据的仓库,数据是有组织的进行存储 (DataBase)DB. 数据库管理系统:操作和管理数据库的大型软件 DataBase Mangement System(DBMS) SQL 操作关系型数据库的编程语言,定义了一套操作关系型数据库统一标准。 1、Oracle 2、MySQL 3…

Face2V人脸向量开发包

Face2V SDK适用于需要人脸检测、人脸特征点和特征向量提取的应用&#xff0c;提供Web API和原生API。官方下载地址&#xff1a;Face2V SDK 。 1、目录组织 Face2V SDK开发包的目录组织说明如下&#xff1a; face2v_sdk | - core # 核心代码目录| -…

docker compose 安装 kafka

一 前置准备 创建 /data/kafkadata /data/zookeeper-1用于保存kafka和zookeeper的配置文件 kafkadata中创建三个文件夹 /kafka1 /kafka2 /kafka3&#xff0c;用于存放三个kafka节点的配置文件 zookeeper-1文件夹中创建 /conf /data /logs /datalog四个文件夹&#xff0c;用于…

【Nuxt】约定式路由和内置组件

约定式路由 手动创建&#xff1a; 或者还可以使用终端创建页面&#xff1a;nuxi-add-page npx nuxi add page about — about.vue npx nuxi add page about/index — about/index.vue <NuxtLink to"/"><button>Home</button></NuxtLink><…

对象存储及其相关概念介绍

对象存储是一种用来描述解决和处理离散单元&#xff08;这些离散单元被称作为对象&#xff09;的方法的通用术语。以下是关于对象存储的详细解析&#xff1a; 一、基本概念 定义&#xff1a;对象存储&#xff0c;也叫做基于对象的存储&#xff0c;是一种将数据以对象的形式进…

JavaScript基础——数据类型转换

显示数据类型转换 String()函数进行显示转换 Number()函数进行显示转换 Boolean()函数进行显示转换 隐式数据类型转换 算术运算隐式转化 比较操作隐式转化 赋值操作 在JavaScript中&#xff0c;数据类型转换是常见的操作&#xff0c;它允许将一种类型的数据转换为另一种…

立项技术路线选择

本章主要是简单聊聊技术路线&#xff0c;额涉及unity和虚幻&#xff0c;目的主要是给自己看的&#xff0c;记录下日期&#xff1a;2024.8.4 在今天&#xff0c;除游戏以外的厂商基本上采用c#的混合技术方案 如果需要的设备对象多。效果不需要极为精细&#xff0c;至少unity是绝…

(自用)MyLog 简单日志 .net6.0 等

appsettings.json {"LogOnOff": true //true 开启日志&#xff1b;false 关闭日志 } MyLog.cs using System.ComponentModel;namespace Namespace {/// <summary>/// 日志类型 枚举/// </summary>public enum LogType{[Description("调试日志&q…

【2024年华数杯全国大学生数学建模竞赛】C题:老外游中国 问题思路分析及Python代码实现

【2024 年华数杯全国大学生数学建模竞赛】C题&#xff1a;老外游中国 问题思路分析及Python代码实现 1 题目 最近&#xff0c;“city 不 city”这一网络流行语在外国网红的推动下备受关注。随着我国过境免签政策的落实&#xff0c;越来越多外国游客来到中国&#xff0c;通过网…

MS1112驱动开发(iio框架)

作者简介&#xff1a; 一个平凡而乐于分享的小比特&#xff0c;中南民族大学通信工程专业研究生在读&#xff0c;研究方向无线联邦学习 擅长领域&#xff1a;驱动开发&#xff0c;嵌入式软件开发&#xff0c;BSP开发 作者主页&#xff1a;一个平凡而乐于分享的小比特的个人主页…

【Java】深度解析Java的反射机制

反射&#xff08;Reflection&#xff09; 一、 反射的基本概念二、 获取类的信息三、 获取类的成员四、 动态创建对象五、 动态调用方法六、 动态访问和修改字段 总结 一、 反射的基本概念 反射是一种运行时机制&#xff0c;允许程序在运行时检查和操作类、方法、字段等。通过…