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

【Golang 面试题】每日 3 题(五十五)

✍个人博客:Pandaconda-CSDN博客
📣专栏地址:http://t.csdnimg.cn/UWz06
📚专栏简介:在这个专栏中,我将会分享 Golang 面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

163. Go hand off 整个分离流程是什么?

当前线程 M 阻塞时,释放 P,给其它空闲的 M 处理。

在这里插入图片描述

164. GMP 中 hand off 机制又是什么?

GMP 中的 hand off 机制是指在某个 M 线程需要将当前正在执行的 Goroutine 交给另一个 M 线程时,使用的一种机制。

具体地,hand off 机制的实现过程如下:

当一个 M 线程需要将当前正在执行的 Goroutine 交给另一个 M 线程时,它会将该 Goroutine 和一个指向目标 M 线程的指针打包成一个结构体,称为 hand off 对象。
当目标 M 线程的本地队列中没有 Goroutine 可供执行时,它会从全局队列中获取一个 hand off 对象,并尝试将其中的 Goroutine 从原来的 M 线程中获取出来,添加到自己的本地队列中执行。在此期间,当前 M 线程会不断尝试从全局队列中获取 Goroutine 并将其调度到本地队列中执行。

当目标 M 线程成功获取到 hand off 对象后,它会将其中的 Goroutine 添加到自己的本地队列中,并将它们调度到绑定的 P 上执行。

hand off 机制的好处是可以避免线程饥饿,提高 Goroutine 的调度效率。当一个 M 线程需要将当前正在执行的 Goroutine 交给另一个 M 线程时,可以使用 hand off 机制来尽快地将 Goroutine 交给目标 M 线程,从而避免线程饥饿的问题。同时,由于 hand off 机制只在需要将当前正在执行的 Goroutine 交给另一个 M 线程时才会被使用,因此相对于 work stealing 机制来说,它的实现比较简单,不会增加太多额外的开销。

165. 如何实现 GMP 中的 hand off 机制?

由于 hand off 机制的使用场景比较特殊,且需要涉及到多个 Goroutine 之间的交互,因此比较难以直接演示。

不过,我们可以通过一个简单的示例来说明 hand off 机制的基本使用方法和效果。
假设我们有一个生产者-消费者模型,其中有多个生产者 Goroutine 和多个消费者 Goroutine,它们都需要不断地从一个共享的队列中获取任务进行处理。为了提高并发效率,我们可以使用 GMP 模型来对任务进行调度。

在这个示例中,我们使用一个全局队列来存储任务,并使用 hand off 机制来将任务从一个 M 线程转移到另一个 M 线程。每个生产者 Goroutine 和消费者 Goroutine 都会不断地尝试从全局队列中获取任务,并将其添加到自己的本地队列中执行。当某个 Goroutine 的本地队列为空时,它会从全局队列中获取一个 hand off 对象,并将其中的 Goroutine 从原来的 M 线程中获取出来,添加到自己的本地队列中执行。在此期间,其他 Goroutine 也可以从全局队列中获取任务,并将其添加到自己的本地队列中执行。

示例代码如下:

package main
import ("fmt""sync""time"
)
// 全局变量,用于保存正在处理的任务
var currentTask int
func producer(tasks chan<- int, wg *sync.WaitGroup) {defer wg.Done()// 生产 10 个任务for i := 1; i <= 10; i++ {fmt.Printf("producer producing task %d\n", i)tasks <- itime.Sleep(time.Second)}// 关闭任务通道close(tasks)
}
func consumer(id int, tasks <-chan int, done chan<- bool, wg *sync.WaitGroup) {defer wg.Done()for task := range tasks {fmt.Printf("consumer %d processing task %d\n", id, task)// 模拟处理任务的耗时time.Sleep(time.Second)// 交出任务,使用 hand off 机制currentTask = taskdone <- true}fmt.Printf("consumer %d has processed all tasks\n", id)
}
func main() {var wg sync.WaitGroup// 任务通道tasks := make(chan int)// done 通道,用于实现 hand off 机制done := make(chan bool)// 启动 3 个 consumer goroutinefor i := 1; i <= 3; i++ {wg.Add(1)go consumer(i, tasks, done, &wg)}// 启动 producer goroutinewg.Add(1)go producer(tasks, &wg)// 等待所有 goroutine 执行完毕wg.Wait()// 所有任务处理完毕后,输出最后一个交出任务的 consumer ID 和任务 IDfmt.Printf("last consumer to hand off task: %d, task ID: %d\n", currentTask%3+1, currentTask)
}

在这个示例中,我们定义了一个全局变量 currentTask,用于保存当前正在处理的任务。在 consumer goroutine 中,当处理完一个任务后,使用 hand off 机制将任务交出,并更新 currentTask 的值。在程序结束时,我们可以通过输出 currentTask 的值来查看最后一个交出任务的 consumer ID 和任务 ID。

http://www.lryc.cn/news/537878.html

相关文章:

  • PHP关键字入门指南:分类与功能全解析
  • 消息中间件深度剖析:以 RabbitMQ 和 Kafka 为核心
  • 【万字详细教程】Linux to go——装在移动硬盘里的Linux系统(Ubuntu22.04)制作流程;一口气解决系统安装引导文件迁移显卡驱动安装等问题
  • HCIA项目实践---OSPF的基本配置
  • Vue 自动配置表单 el-switch等不常用组件覆盖默认值问题
  • 零基础购买阿里云服务器,XShell连接云服务器
  • 【系统架构设计师】虚拟机体系结构风格
  • C语言中qsort函数使用技巧
  • WPF的Prism框架的使用
  • LeetCode每日精进:142.环形链表II
  • CPP集群聊天服务器开发实践(五):nginx负载均衡配置
  • easyexcel解析excel文件的时候报错
  • Android设备 网络安全检测
  • word分栏使得最后一页内容自动平衡
  • 完全免费稳定WebTerm网页版在线SSH连接,在线远程连接云服务器,可以控制背景,支持SFTP访问服务器文件。无需安装即可在线连接和管理服务器的SSH终端工具。支持跨平台设备。
  • 微信小程序医院挂号系统
  • 编程题-最大子数组和(中等-重点【贪心、动态规划、分治思想的应用】)
  • 阿里云视频点播,基于thinkphp8上传视频
  • 《探秘AI绿色计算:降低人工智能硬件能耗的热点技术》
  • 神经网络常见激活函数 9-CELU函数
  • 软考高级《系统架构设计师》知识点(四)
  • opencv交叉编译
  • 安装vite报错Install for [ ‘create-vite@latest‘ ] failed with code 1
  • Spring框架中都用到了哪些设计模式?
  • LabVIEW 中 dotnet.llb 库功能
  • C# 变量,字段和属性的区别
  • wordpress模板文件结构超详解
  • android studio下载安装汉化-Flutter安装
  • 数据开放共享和平台整合优化取得实质性突破的智慧物流开源了
  • 如何设置 Nginx 连接超时并进行测试(Nginx优化)