Go进阶概览 -【5.3 select的底层实现及工作原理】

5.3 select的底层实现及工作原理

select语句是Go语言中用于处理多个通道操作的一个强大工具,它能够在多个通道上同时进行非阻塞的选择操作。这对于实现并发程序的灵活性和复杂性处理非常有帮助。

本节我们将详细探讨select的内部实现及工作原理。

本节代码存放目录为 lesson15

select的底层实现

select的基本结构

select语句的实现涉及到以下几个核心部分:

  • 通道的case列表select语句中每个case会对应一个通道操作,编译器会将这些case打包成一个select操作列表。

    case结构如下所示:

    type scase struct {c    *hchan         // chanelem unsafe.Pointer // data element
    }
    
  • 随机化:为了避免select语句的饥饿问题(总是先处理某个case),Go语言的实现会对case列表进行随机化处理。

  • 阻塞队列:如果所有的通道都无法立即进行操作,select语句会将当前的Goroutine加入到每个通道的等待队列中,并阻塞Goroutine,直到某个通道的操作可以进行。

  • 唤醒与继续:当某个通道的操作可以进行时,select会唤醒相关的Goroutine,并继续执行与该通道关联的case


select的操作流程

我们可以以下步骤理解select的操作流程:

  1. 初始化selectcase列表:编译器将每个case操作(通道的接收或发送)打包到一个列表中。

  2. 随机化case列表:为了避免饥饿,运行时会对这个case列表进行随机打乱,使得每次select的执行顺序都是随机的。

  3. 遍历case列表

    • 对于每个caseselect语句会检查对应通道是否可以立即进行操作。

    • 如果可以,则直接执行该case,并结束select语句。

    • 如果不可以,则将当前Goroutine加入到该通道的等待队列中。

  4. 阻塞当前Goroutine

    • 如果所有的通道都不能立即操作,select语句将阻塞当前的Goroutine,直到其中一个通道可以进行操作。

    • 当某个通道准备好后,该Goroutine会被唤醒,执行与该通道关联的case

  5. 默认情况default

    • 如果select语句中存在default分支,并且所有通道都不能操作,那么select会立即执行default分支,而不会阻塞。

我们可以通过下面的示意图来进行理解:

┌────────────────────────┐
│       select           │
│  ┌───────────────────┐ │
│  │ case1: <- ch1     │ │
│  │ case2: <- ch2     │ │
│  │ case3: <- ch3     │ │
│  └───────────────────┘ │
└────────────────────────┘│▼
┌─────────────────────────┐
│     运行时随机化          │
│  随机打乱 case 列表       │
└─────────────────────────┘│▼
┌─────────────────────────┐
│  顺序检查 case           │
│  检查 case1、case2...    │
│  按随机后的顺序           │
└─────────────────────────┘│▼
┌─────────────────────────┐
│  执行一个可以操作的 case   │
│  例如:执行 case2         │
└─────────────────────────┘│▼select 语句结束

select的实现原理

Go语言中的select语句依赖于调度器和通道的底层机制来实现。具体来说:

  • 调度器select语句会与Go调度器紧密合作,当select阻塞时,调度器会将当前Goroutine挂起,并将其加入到通道的等待队列中。

  • 通道的队列:每个通道都有发送和接收的等待队列。当select中的某个通道准备好时,通道的机制会从队列中唤醒对应的Goroutine

  • 唤醒机制:当通道的状态发生变化时(例如一个通道的数据被接收或发送),通道会通过调度器唤醒阻塞在其上的Goroutine,然后继续执行select语句的逻辑。

性能与使用建议

虽然select非常强大,但是在使用时也有一些性能和设计方面的考虑:

  1. 避免滥用select:在高并发场景下,如果select语句处理的通道数量过多,可能会带来一些性能开销。

  2. 使用default分支:在某些情况下,添加default分支可以防止select语句永久阻塞,从而提高程序的响应性。

  3. 关注select的随机性:由于select语句的case选择是随机化的,因此不要依赖某个固定的选择顺序,这样可以避免一些难以调试的问题。

下面代码演示了一个常用的使用案例:

func main() {ch1 := make(chan int64, 2)ch2 := make(chan int64, 2)ch3 := make(chan int64, 2)wg.Add(1)go func() {defer wg.Done()for {ch1 <- time.Now().Unix()time.Sleep(time.Duration(1) * time.Second)ch2 <- time.Now().Unix()time.Sleep(time.Duration(1) * time.Second)ch3 <- time.Now().Unix()time.Sleep(time.Duration(1) * time.Second)}}()wg.Add(1)go func() {defer wg.Done()for {select {case t1 := <-ch1:fmt.Println("Received from ch1, ", t1)case t2 := <-ch2:fmt.Println("Received from ch2, ", t2)case t3 := <-ch3:fmt.Println("Received from ch3, ", t3)}}}()wg.Wait()
}

小结

select的主要作用就是用于对多个通道执行读取操作,这样一方面我们可以简化我们的程序,一方面我们也可以通过select执行一些流程操作。

select本质上就属于是监听了多个通道,所以我们不适合在select中使用大批量的case


我的GitHub:https://github.com/swxctx

书籍地址:https://d.golang.website/

书籍代码:https://github.com/YouCanGolang/GoDeeperCode

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

mysql通过binlog做数据恢复

1 介绍 binlog&#xff08;二进制日志&#xff09;在 MySQL 中具有非常重要的作用。它记录了数据库的所有更改操作&#xff0c;主要用于数据恢复、复制和审计等方面。以下是 binlog 的主要作用&#xff1a; 1.数据恢复 binlog 可以用于恢复数据库中的数据。当数据库发生故障时…

分布式框架 - ZooKeeper

一、什么是微服务架构 1、单体架构 顾名思义一个软件系统只部署在一台服务器上。 ​ 在高并发场景中&#xff0c;比如电商项目&#xff0c;单台服务器往往难以支撑短时间内的大量请求&#xff0c;聪明的架构师想出了一个办法提高并发量&#xff1a;一台服务器不够就加一台&am…

微信小程序拨打电话点取消报错“errMsg“:“makePhoneCall:fail cancel“

问题&#xff1a;微信小程序中拨打电话点取消&#xff0c;控制台报错"errMsg":"makePhoneCall:fail cancel" 解决方法&#xff1a;在后面加上catch就可以解决这个报错 wx.makePhoneCall({phoneNumber: 181********}).catch((e) > {console.log(e) //用…

数据安全治理

数据安全治理 1.数据安全治理2.终端数据安全加密类权限控制类终端DLP类桌面虚拟化安全桌面 3.网络数据安全4.存储数据安全5.应用数据安全6.其他话题数据脱敏水印与溯源 7.UEBA8.CASB 1.数据安全治理 数据安全治理最为重要的是进行数据安全策略和流程制订。在企业或行业内经常发…

前端实用工具(二):编程规范化解决方案

目录 本地代码规范化工具 代码检测工具ESLint 代码格式化工具Prettier 远程代码规范化工具 远程提交规范化工具commitizen 提交规范检验工具commitlint husky 什么是git hooks commitlint安装 husky安装 检测代码提交规范 ESLint husky 自动修复格式错误lint-staged…

使用 Puppeteer-Cluster 和代理进行高效网络抓取: 完全指南

文章目录 一、介绍&#xff1f;二、什么是 Puppeteer-Cluster&#xff1f;三、为什么代理在网络抓取中很重要&#xff1f;四、 为什么使用带代理的 Puppeteer-Cluster&#xff1f;五、分步指南&#xff1a; 带代理的 Puppeteer 群集5.1. 步骤 1&#xff1a;安装所需程序库5.2. …

基于 ROS 的Terraform托管服务轻松部署ChatGLM2-6B

介绍 ChatGLM2-6B是开源中英双语对话模型ChatGLM-6B的第二代版本&#xff0c;在保留了初代模型对话流畅、部署门槛较低等众多优秀特性的基础上&#xff0c;ChatGLM2-6B具有更强大的性能、更长的上下文、更高效的推理等特性。 资源编排服务&#xff08;Resource Orchestration…

C++入门 之 类和对象(下)

目录 一、初始化列表 二、隐式类型转换与explict 三、静态成员——static 四、友元 五、内部类 六、匿名对象 七.对象拷贝时的编译器优化 一、初始化列表 之前我们实现构造函数时&#xff0c;初始化成员变量主要使用函数体内赋值&#xff0c;构造函数初始化还有一种方式&…

闯关leetcode——66. Plus One

大纲 题目地址内容 解题代码地址 题目 地址 https://leetcode.com/problems/plus-one/description/ 内容 You are given a large integer represented as an integer array digits, where each digits[i] is the ith digit of the integer. The digits are ordered from mo…

pdf文件怎么直接翻译?使用这些工具让翻译变得简单

在全球化日益加深的职场环境中&#xff0c;处理外语PDF文件成为了许多职场人士面临的共同挑战。 面对这些“加密”的信息宝库&#xff0c;如何高效、准确地将英文pdf翻译成对应语言&#xff0c;成为了提升工作效率的关键。 以下是几款在PDF翻译领域表现出色的软件&#xff0c…

基于 UniApp 平台的学生闲置物品售卖小程序设计与实现

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

寄存器二分频电路

verilog代码 module div2_clk ( input clk, input rst,output clk_div);reg clk_div_r; assign clk_div clk_div_r;always(posedge clk) beginif(rst)beginclk_div_r < 1b0;endelsebeginclk_di…

pytorch实现RNN网络

目录 1.导包 2. 加载本地文本数据 3.构建循环神经网络层 4.初始化隐藏状态state 5.创建随机的数据&#xff0c;检测一下代码是否能正常运行 6. 构建一个完整的循环神经网络 7.模型训练 8.个人知识点理解 1.导包 import torch from torch import nn from torch.nn imp…

API安全推荐厂商瑞数信息入选IDC《中国数据安全技术发展路线图》

近日&#xff0c;全球领先的IT研究与咨询公司IDC发布报告《IDC TechScape&#xff1a;中国数据安全技术发展路线图&#xff0c;2024》。瑞数信息凭借其卓越的技术实力和广泛的行业应用&#xff0c;被IDC评选为“增量型”技术曲线API安全的推荐厂商。 IDC指出&#xff0c;数据安…

Liveweb视频汇聚平台支持GB28181转RTMP、HLS、RTSP、FLV格式播放方案

GB28181协议凭借其在安防流媒体行业独有的大统一地位&#xff0c;目前已经在各种安防项目上使用。雪亮工程、幼儿园监控、智慧工地、物流监控等等项目上目前都需要接入安防摄像头或平台进行直播、回放。而GB28181协议作为国家推荐标准&#xff0c;目前基本所有厂家的安防摄像头…

Netty源码解析-请求处理与多路复用

Netty基本介绍&#xff0c;参考 Netty与网络编程 摘要 Netty源码系列-NioEventLoop 1.1 Netty给Channel分配Nio Event Loop的规则 看下图&#xff0c;EventLoopGroup是线程组&#xff0c;每个EventLoop是一个线程&#xff0c;那么线程处理请求是怎么分配的呢&#xff1f;我…

Docker 以外置数据库方式部署禅道

2.安装步骤 2.1.参考资料 禅道官网文档: https://www.zentao.net/book/zentaopms/docker-1111.html https://www.zentao.net/book/zentaopms/405.html 2.2.详细步骤 ssh 登录服务器创建目录 /opt/zentao /opt/zentao/data /opt/zentao/db cd /opt mkdir zentao mkdir zentao…

回归预测 | Matlab实现SSA-HKELM麻雀算法优化混合核极限学习机多变量回归预测

回归预测 | Matlab实现SSA-HKELM麻雀算法优化混合核极限学习机多变量回归预测 目录 回归预测 | Matlab实现SSA-HKELM麻雀算法优化混合核极限学习机多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现SSA-HKELM麻雀算法优化混合核极限学习机多变量…

java -versionbash:/usr/lib/jvm/jdk1.8.0_162/bin/java:无法执行二进制文件:可执行文件格式错误

实验环境&#xff1a;Apple M1在VMwareFusion使用Utubun Jdk文件错误 &#xfffc; 尝试&#xff1a; 1、重新在网盘下载java1.8 2、在终端通过命令下载 3、确保 JDK 正确安装在系统中&#xff0c;可以通过 echo $JAVA_HOME 检查 JAVA_HOME 环境变量是否设置正确。 &#xfff…

十种果冻的做法

菠萝果冻 1.在菠萝的1/5处切开&#xff0c;切去顶做盖子用&#xff0c;用水果刀在四周划一圈使皮和果肉分离 2.注意底部切透了&#xff0c;用水果刀把菠萝肉挖出&#xff0c;菠萝肉切丁用盐水浸泡备用 3.把菠萝丁放入料理机中加入少许纯净水&#xff0c;打成菠萝汁备用 4.打好…