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

Go语言并发之Select多路选择操作符

1、Go语言并发之Select多路选择操作符

select 是类 UNIX 系统提供的一个多路复用系统 API,Go 语言借用多路复用的概念,提供了 select 关键字,用

于多路监听多个通道。当监听的通道没有状态是可读或可写的,select 是阻塞的;只要监听的通道中有一个状态

是可读或可写,则 select 就不会阻寒,而是进入处理就绪通道的分支流程。如果监听的通道有多个口读或口写

的状态,则 select 随利选取一个处理。

package mainfunc main() {ch := make(chan int, 1)go func(chan int) {for {select {// 0或者1写入是随机的case ch <- 0:case ch <- 1:}}}(ch)for i := 0; i < 10; i++ {println(<-ch)}}
# 程序结果
1
1
1
1
0
0
0
0
1
1

1.1 多路选择操作符 select

在golang语言中,select 语句就是用来监听和channel有关的IO操作,当IO操作发生时,触发相应的case动作。

有了select语句,可以实现 main 主线程与 goroutine 线程之间的互动。

select使用时类似 switch-case 的用法,适用于处理多通道的场景,会通过类似 are-you-ready-polling 的机制

来工作。

select {case <-ch1 :     // 检测有没有数据可读// 一旦成功读取到数据,则进行该case处理语句case ch2 <- 1 :  // 检测有没有数据可写// 一旦成功向ch2写入数据,则进行该case处理语句default:// 如果以上都没有符合条件,那么进入default处理流程
}
  • select 语句只能用于 channel 信道的IO操作,每个 case 都必须是一个信道。

  • 如果不设置 default 条件,当没有IO操作发生时,select 语句就会一直阻塞。

  • 如果有一个或多个IO操作发生时,Go运行时会随机选择一个 case 执行,但此时将无法保证执行顺序。

  • 对于 case 语句,如果存在信道值为 nil 的读写操作,则该分支将被忽略,可以理解为相当于从select语句中

    删除了这个case;

  • 对于空的 select 语句,会引起死锁;

  • 对于在 for中的select语句,不能添加 default,否则会引起cpu占用过高的问题;

  • 随机性:多个 case 之间并非顺序的,遵循「先到先执行,同时到则随机执行」的原则。

  • 一次性:和 switch-case 一样,select-case也只会执行一次,如果需要多次处理,需要在外层套一个循环。

  • default 不会阻塞,会一直执行,当与 for 循环组合使用时可能出现死循环。

1.2 阻塞与非阻塞 select

select 默认是阻塞的,当没有 case 处于激活状态时,会一直阻塞住,极端的甚至可以这样用:

package mainfunc main() {select {// 啥也不干,一直阻塞住}
}

执行后,引发死锁,打印如下:

# 输出
fatal error: all goroutines are asleep - deadlock!goroutine 1 [select (no cases)]:

通过增加 default,可以实现非阻塞的 select:

select {case x, ok := <-ch1:...case ch2 <- y:...default:fmt.Println("default")}

1.3 多 case 与 default 执行的顺序

整体流程如图所示:
在这里插入图片描述

1.4 多个IO操作发生时,case语句是随机执行的

package mainimport "fmt"func main() {// 创建一个长度带缓冲的整型通道ch1 := make(chan int, 1)// 向通道中写入数据ch1 <- 1ch2 := make(chan int, 1)ch2 <- 2select {case <-ch1:fmt.Println("ch1 read")case <-ch2:fmt.Println("ch2 read")}
}

多次执行后,会随机打印 ch1 read 或 ch2 read。

1.5 for中的select 引起CPU资源消耗过高

package mainimport ("fmt""time"
)func main() {quit := make(chan bool)go func() {for {select {case <-quit:fmt.Println("quit")// 使用 return 就会退出整个goroutine线程;如果使用 break,程序仍然在for循环中执行returndefault:fmt.Println("default")}}}()time.Sleep(3 * time.Second)quit <- true // 主线程在3秒后,向quit信道写入数据time.Sleep(2 * time.Second)fmt.Println("main")
}
# 程序结果
default
default
default
default
default
default
default
......
......
default
default
default
default
default
quit
main

在 for{} 的 select 语句中使用了 default 后,线程就会无限执行 default 条件,直到 quit 信道中读到数据,否

则会一直在一个死循环中运行,从而导致占满整个CPU资源。

在 for{} 的 select 语句中,不建议使用 default 条件。

1.6 select语句的实际应用

(1)、实现 main主线程与 goroutine线程之间的交互、通信

package mainimport ("bufio""fmt""os"
)// 通过控制台输入"bye",来控制main函数结束运行
func main() {quit := make(chan bool)ch := make(chan string)go func() {for {select {case name := <-ch:fmt.Printf("from main msg: [%v]\n", name)if name == "bye" {quit <- true} else {quit <- false}}}}()for {// 控制台输入fmt.Print("please input string: ")scanner := bufio.NewScanner(os.Stdin)scanner.Scan()ch <- scanner.Text()isOver := <-quitif isOver {break}}fmt.Println("main over")
}
# 输出
please input string: from main msg: [ttttt]
please input string: from main msg: [qqqq]
please input string: from main msg: [wwww]
please input string: from main msg: [bye]
main over

(2)、超时实现

package mainimport ("fmt""time"
)func main() {quit := make(chan bool)ch := make(chan int)go func() {for {select {case num := <-ch:fmt.Println("num = ", num)case <-time.After(5 * time.Second):fmt.Println("超时")quit <- true}}}()for i := 0; i < 2; i++ {ch <- itime.Sleep(time.Second)}<-quit // 等待超时后, 结束 main主线程fmt.Println("程序结束")
}
# 输出结果
num =  0
num =  1
超时
程序结束

1.7 select使用的区别

package mainimport ("fmt""time"
)func server1(ch chan string) {time.Sleep(6 * time.Second)ch <- "from server1"
}func server2(ch chan string) {time.Sleep(3 * time.Second)ch <- "from server2"
}func main() {output1 := make(chan string)output2 := make(chan string)go server1(output1)go server2(output2)s1 := <-output1fmt.Println(s1)s2 := <-output2fmt.Println(s2)
}
# 程序结果
from server1
from server2
package mainimport ("fmt""time"
)func server1(ch chan string) {time.Sleep(6 * time.Second)ch <- "from server1"
}func server2(ch chan string) {time.Sleep(3 * time.Second)ch <- "from server2"
}func main() {output1 := make(chan string)output2 := make(chan string)go server1(output1)go server2(output2)select {case s1 := <-output1:fmt.Println(s1)case s2 := <-output2:fmt.Println(s2)}
}
# 程序结果
from server2
package mainimport "time"import ("fmt"
)// select 管道参数并行func server1(ch chan string) {time.Sleep(time.Second * 6)ch <- "response from server1"
}func server2(ch chan string) {time.Sleep(time.Second * 3)ch <- "response from server2"
}func main() {output1 := make(chan string)output2 := make(chan string)go server1(output1)go server2(output2)// 管道同时ready,select随机执行// time.Sleep(time.Second)select {case s1 := <-output1:fmt.Println("s1:", s1)case s2 := <-output2:fmt.Println("s2:", s2)default:fmt.Println("run default")}
}
# 程序结果
run default
package mainimport ("fmt""time"
)func server1(ch chan string) {ch <- "from server1"
}func server2(ch chan string) {ch <- "from server2"
}func main() {output1 := make(chan string)output2 := make(chan string)go server1(output1)go server2(output2)time.Sleep(1 * time.Second)select {case s1 := <-output1:fmt.Println(s1)case s2 := <-output2:fmt.Println(s2)}
}
# 输出
from server2 和 from server1 随机交替

相关文章:

Go语言并发之Select多路选择操作符

1、Go语言并发之Select多路选择操作符 select 是类 UNIX 系统提供的一个多路复用系统 API&#xff0c;Go 语言借用多路复用的概念&#xff0c;提供了 select 关键字&#xff0c;用 于多路监听多个通道。当监听的通道没有状态是可读或可写的&#xff0c;select 是阻塞的&#…...

黄金回收小程序开发功能有哪些?

一、用户端&#xff1a; 1、实时查询&#xff1a;通过对接三方接口实现实时金价动态查看&#xff1b; 2、多种类珠宝实时回收&#xff1a;小程序支持多品类珠宝的实时回收包含黄金饰品、金条、铂金、K金、白银等&#xff0c;同步实现价格实时更新&#xff1b; …...

nginx的详解与应用

前言 说明 要义 nginx 有一个master 进程和多个worker 进程。主进程的主要目的是读取和评估配置&#xff0c;以及维护工作进程。工作进程对请求进行实际处理。nginx 采用基于事件的模型和依赖于操作系统的机制在工作进程之间有效地分发请求。工作进程的数量在配置文件中定义…...

SpringBoot激活profiles的几种方式

多环境是最常见的配置隔离方式之一&#xff0c;可以根据不同的运行环境提供不同的配置信息来应对不同的业务场景&#xff0c;在SpringBoot内支持了多种配置隔离的方式&#xff0c;可以激活单个或者多个配置文件。 激活的profiles要在项目内创建对应的配置文件&#xff0c;格式…...

【Java】Java核心要点总结:58

文章目录 1. java中 怎么确保一个集合不能被修改2. 队列和栈是什么 有什么区别3. Java8开始的ConcurrentHashMap为什么舍弃了分段锁4. ConcurrentHashMap 和 Hashtable有什么区别5. ReadWriteLock和StampeLock 1. java中 怎么确保一个集合不能被修改 Java 中可以使用 Collectio…...

前端面试题---作用域链和原型链

一.JavaScript 中的作用域链是如何工作的? JavaScript 中的作用域链&#xff08;Scope chain&#xff09;是一种用于查找变量和函数的机制&#xff0c;它是由嵌套的作用域环境组成的链式结构。 当在 JavaScript 中访问一个变量或函数时&#xff0c;解析器会首先在当前作用域…...

零售品牌私域流量池如何运营?火山引擎数智平台提供全套产品组合

虽然距离6月18日还有两周时间&#xff0c;但各大平台的第一波618战绩&#xff08;预售尾款&#xff09;已经相继出炉。 5月31日晚8点&#xff0c;京东率先公布618开门红10分钟销售战报&#xff1a;10分钟内&#xff0c;成交额破亿品牌数同比增长23%&#xff0c;超六成的新商家…...

rk3568 SD卡启动

rk3568 SD卡启动 SD卡启动系统&#xff0c;它可以让rk3568在没有硬盘或其他存储设备的情况下启动和运行操作系统。这使得rk3568变得与树梅派一样灵活切换系统&#xff0c;与此同时进行故障排查和修复&#xff0c;而不需要拆卸设备或者使用专业的烧录工具。SD卡启动还可以方便地…...

English Learning - L3 作业打卡 Lesson5 Day34 2023.6.7 周三

English Learning - L3 作业打卡 Lesson5 Day34 2023.6.7 周三 引言&#x1f349;句1: The woman reading the romantic novel could be a lawyer.成分划分弱读连读爆破语调 &#x1f349;句2: She just wants a light read to take her mind off work.成分划分弱读连读爆破语调…...

【运筹优化】最短路算法之A星算法 + Java代码实现

文章目录 一、A星算法简介二、A星算法思想三、A星算法 java代码四、测试 一、A星算法简介 A*算法是一种静态路网中求解最短路径最有效的直接搜索方法&#xff0c;也是解决许多搜索问题的有效算法。算法中的距离估算值与实际值越接近&#xff0c;最终搜索速度越快。 二、A星算…...

[6]PCB设计实验|认识常用元器件|电阻器|18:30~19:00

目录 一、电阻器主要用途 1. 稳定和调节电路中的电流和电压 2. 作为分流、分压和负载使用 二、常见电阻器 1. 贴片电阻 2. 热敏电阻 3. 限流电阻 4. 可调电阻 5. 排阻(网络电阻) 三、几种常用电阻器的结构特点 四、电阻的参数 1. 额定功率 电阻器功率的表示 ​2…...

Webots R2021a教程

文章目录 Windows安装设置中文打开世界添加贴图 为外部控制器配置Anaconda解决报错&#xff1a;CondaSSLError: Encountered an SSL error. Most likely a certificate verification issue.调用Python API Windows 安装 进入下载页面 https://github.com/cyberbotics/webots/r…...

C++ 输出格式控制

C 输出格式控制 需包含头文件&#xff1a; 浮点数精度、域宽、填充 操作符功能right-alignedright-alignedsetprecision(int n)设置以n表示的数值精度setw(int n)设置以n表示的域宽setfill(char c)设置以c表示的填充字符 输出格式 操作符功能oct以八进制格式输出数据dec以…...

【C++】引用和右值引用

目录 1. 引用 1.1 引用的概念 1.2 引用的特性 1.3 引用的使用场景 1.3.1 作为参数 1.3.2 作为返回值 1.4 常量引用 1.5 引用和指针的区别 2. 左值和右值 3. 右值引用 3.1 右值引用的概念 3.2 左值持久&#xff1b;右值短暂 3.3 变量是左值 3.4 标准库move函数 1.…...

NodeJS MongoDB⑦

文章目录 ✨文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持&#x1f618;前言Node&MongoDB 第一步 连接数据库 第二步 创建User Mongodb模型 第三步 简单使用 Mongodb命令 第四步 规范使用 Mongodb命令 &#xff08…...

情感分析实战(中文)-共现语义篇

情感分析实战(中文)-共现语义网络分析 背景:该专栏的目的是将自己做了N个情感分析的毕业设计的一个总结版,不仅自己可以在这次总结中,把自己过往的一些经验进行归纳,梳理,巩固自己的知识从而进一步提升,而帮助各大广大学子们,在碰到情感分析的毕业设计时,提供一个好的…...

【数据结构与算法】03 队列(顺序队列--循环队列--优先级队列--链队列)

一、概念1.1 队列的基本概念1.2 队列的顺序存储结构1.21 顺序队列&#xff08;静态队列&#xff09;1.22 循环队列1.23 优先级队列 1.3 队列的链式存储结构 二、C语言实现2.1 顺序存储2.11 顺序队列2.12 循环队列2.13 优先级队列 2.2 链式存储 一、概念 1.1 队列的基本概念 队…...

【区块链 | L2】作为Layer2赛道的领跑者,如何理解 Arbitrum?

上周我们介绍了以太坊L2扩展解决方案Optimism,本周我们继续介绍另一个L2解决方案——Arbitrum。Arbitrum 是以太坊的一个 Optimistic Rollup L2 可扩展性解决方案。 Part.1 什么是Arbitrum? Arbitrum 是一个构建在以太坊之上的区块链网络。你可以使用 Arbitrum 链来做任何在…...

【协议】NVMe over RoCE |nvmeof

什么是nvme nvme ssd和普通ssd区别 ssd是固态硬盘&#xff0c;普通的ssd配的是SATA口&#xff08;AHCI协议&#xff09;&#xff0c;nvme ssd配的是PCIe口&#xff08;nvme传输协议&#xff09; 相比普通SSD的SATA口&#xff0c;nvme的PCIe口有巨大的性能优势。 更多详情见&…...

硬件设计电源系列文章-DCDC转换器布局设计

文章目录 概要 整体架构流程 技术名词解释 1.开关电源PCB布局要点 2.输入电容的放置 3.二极管的放置 4.散热孔的放置 5.反馈路径的走线 小结 概要 提示&#xff1a;这里可以添加技术概要 例如&#xff1a; 本文主要DCDC转换器布局方面的知识。 整体架构流程 提示&#xf…...

「从入门到精通,一位设计师分享学习Illustrator的技巧和经验!」

学习Illustrator的个人笔记&#xff1a;从入门到精通 Adobe Illustrator是一款广泛使用的矢量图形软件&#xff0c;用于创建各种设计作品&#xff0c;如商标、海报、名片等。在本篇博客中&#xff0c;我将分享学习Illustrator的经验和技巧&#xff0c;帮助您更好地掌握这一工具…...

RedisGraph的整体架构

The architecture of RedisGraph 本文关注RedisGraph的整体架构&#xff0c;分别从图存储模型、索引、并发控制、和执行计划四个方面简要阐述。下图为RedisGraph的整体架构图。 1 图存储模型 了解一个图数据库的架构&#xff0c;最重要的就是其图存储模型&#xff0c;即其中的…...

C#可视化 家用轿车信息查询系统(具体做法及全部代码)

目录 题目&#xff1a; 效果图&#xff1a; 数据库&#xff1a; 做法&#xff1a; combobox值更新 查询按钮功能&#xff08;非空验证&#xff0c;查询数据&#xff09; datagirdview设置 全部代码&#xff1a; DBHelper类 From1主窗体代码 题目&#xff1a; 效果图&#…...

Nautilus Chain全球行分享会,上海站圆满举办

在北京时间 6 月 9 日&#xff0c;由 Nautilus Chain 主办的“Layer3 模块化区块链的发展探讨”为主题的全球行活动&#xff0c;在上海顺利举办&#xff0c;本次分享会联合主办方还包 括 Stanford Blockchain Accelerator、Zebec Protocol、Tiger VC DAO、Crypto PHD、Rootz La…...

day50_mybatis

今日内容 0 复习昨日 一、分页插件 二、ORM映射【重点】 三、多表联查 【重点】 四、动态SQL 【重点】 五、$和# 零、复习昨日 mybatis orm框架,作用于持久层,高效开发,只关注sql,其他不用关心 思考MyBatis到底帮你省了哪些事情? jdbc第四步sql自己编写之外,其他mybatis都做了…...

第十一届“创业江苏”科技创业大赛正式启动

为深入实施创新驱动战略&#xff0c; 推进高水平科技自立自强&#xff0c;强化企业创新主体地位&#xff0c;加速推动创新要素向企业集聚&#xff0c;促进科技和金融深度融合&#xff0c;优化科技创新创业生态&#xff0c;吸引优秀创业团队及企业到苏州创新发展&#xff0c;根据…...

EasyX实现简易贪吃蛇

&#x1f4dd;个人主页&#xff1a;认真写博客的夏目浅石. &#x1f4e3;系列专栏&#xff1a;夏目的C语言宝藏 文章目录 前言一、头文件包含二、创建蛇与食物的结构体三、游戏的初始化四、游戏的绘画事件五、蛇的移动事件六、输入方向七、生成食物八、吃食物九、游戏失败的判定…...

Linux下ElasticSearch7.9.2安装配置(包含服务器配置、启动停止脚本、开放端口和elasticsearch-head插件的使用)

Linux下ElasticSearch7.9.2安装配置 前言1.下载安装1.1 使用wget的方式下载1.2 官网下载 2.上传到服务器并解压3.修改es配置文件3.1 es目录简介3.2 修改配置文件 4. 创建用户并赋权5. 服务器修改配置5.1 修改文件句柄数和线程数5.2 关闭swapping5.3 修改虚拟内存 6. 启动es6.1 …...

JS 之 事件Event对象详解(属性、方法、自定义事件)

一、Event对象 1、简介 ​ 事件event对象是指在浏览器中触发事件时&#xff0c;浏览器会自动创建一个event对象&#xff0c;其中存储了本次事件相关的信息&#xff0c;包括事件类型、事件目标、触发元素等等。浏览器创建完event对象之后&#xff0c;会自动将该对象作为参数传…...

65寸电视长宽多少厘米

65寸电视的长和宽分别是多少 65寸电视机尺寸是不确定的&#xff0c;要看电视的品牌和具体型号。一般来说&#xff0c;16&#xff1a;9屏幕比例下&#xff0c;65英寸电视的长宽分别为143.90厘米和80.94厘米。电视尺寸指的是电视屏幕对角线的长度&#xff0c;目前电视尺寸普遍以英…...

前端需要会wordpress/网页广告

文本框失去焦点事件、获得焦点事件onBlur:当失去输入焦点后产生该事件onFocus:当输入获得焦点后&#xff0c;产生该文件Onchange:当文字值改变时&#xff0c;产生该事件Onselect:当文字加亮后&#xff0c;产生该文件onpropertychange 当属性改变发生该事件无论粘贴 keyup oncha…...

dhl网站做形式发票/域名污染查询网站

继承:子类对象可以使用父类中的属性或方法的过程,叫做继承 格式: class 子类名(父类名): object是所有类的公共父类,基类,顶级类 如果使用经典类,或者新式类中括号内什么也不写,其实默认就继承了object class Person(object): pass class Man(Person): pass class Boy(Ma…...

医疗网站前置审批要多长时间/推广平台app

正则表达式的分组及在pandas中的实用操作1. 正则表达式分组1.1 分组的模式1.2 分组的实际操作1.2.1 邮箱号码匹配1.2.2 标签信息匹配2. pandas中的应用操作2.1 导入库&#xff0c;读取文件数据&#xff0c;并输出指定的字段2.2 提取数据&#xff0c;创建新字段3. 小结之前的博客…...

wordpress+刷新/怎么制作一个网页

作者&#xff1a;chris 来自&#xff1a;IBM 很多人用java进行文档操作时经常会遇到一个问题&#xff0c;就是如何获得word&#xff0c;excel&#xff0c;pdf等文档的内容&#xff1f;我研究了一下&#xff0c;在这里总结一下抽取word,pdf的几种方法。 1. 用jaco…...

速度快的wordpress主机/正规网站优化哪个公司好

你知道如何在Excel中计算平方和吗&#xff1f;在Excel中查找平方和是一项重复的任务。最常用的公式需要大量数据输入。下面小编为你介绍一种简单好用的方法&#xff0c;让你可以快速计算平方和&#xff01;Microsoft Excel 2019 for Mac​www.macz.com查找多个单元的平方和在Ex…...

有没有网站找人帮忙做图/企业网站排名优化价格

我们今天所熟悉的数字音乐来自1999年的Napster。通过Napster&#xff0c;你可以免费从网上下载MP3音乐文件&#xff0c;毫无疑问&#xff0c;此举遭到了唱片公司的封杀&#xff0c;在往后的两年中&#xff0c;唱片公司一直在试图扑灭数字音乐之火&#xff0c;直到2001年。 2001…...