Golang 并发编程:Context 包的使用与并发控制
文章目录
- 一、简介
- 二、Context 的基本概念
- 1. `context` 包常用函数
- 三、Context 的基本用法
- 1. `WithCancel`:取消任务的上下文
- 四、超时控制:`WithTimeout` 和 `WithDeadline`
- 1. 使用 `WithTimeout` 控制任务超时
- 2. 使用 `WithDeadline` 设定截止时间
- 五、传递上下文中的数据:`WithValue`
- 六、Context 的应用场景
- 七、完整示例:多任务协作控制
- 八、小结
一、简介
在并发编程中,任务管理和资源控制是非常重要的,而 Golang 的 context 包 为我们提供了一种优雅的方式来传递取消信号和超时控制。Context 用于在多个 Goroutine 之间传递上下文信息,避免 Goroutine 无法按需停止而导致资源浪费。
本篇博客将详细介绍 context 包的用法,并通过实例讲解如何在超时、取消任务和多 Goroutine 协作场景中使用它。
二、Context 的基本概念
Context 是一种携带取消信号、截止时间(超时)和元数据的上下文对象,主要用于父 Goroutine 与子 Goroutine 的协作。它通过层级化的结构来管理多个并发任务。
1. context 包常用函数
context.Background():创建根上下文,通常用于程序入口。context.TODO():占位符上下文,表示未来会替换为实际上下文。context.WithCancel(parent Context):创建带取消功能的子上下文。context.WithTimeout(parent Context, timeout time.Duration):创建带超时功能的子上下文。context.WithDeadline(parent Context, deadline time.Time):基于指定的截止时间创建上下文。context.WithValue(parent Context, key, value interface{}):传递携带额外数据的上下文。
三、Context 的基本用法
1. WithCancel:取消任务的上下文
示例:使用 WithCancel 取消 Goroutine
package mainimport ("context""fmt""time"
)func worker(ctx context.Context, id int) {for {select {case <-ctx.Done(): // 接收取消信号fmt.Printf("Worker %d stopped\n", id)returndefault:fmt.Printf("Worker %d is working...\n", id)time.Sleep(time.Second)}}
}func main() {ctx, cancel := context.WithCancel(context.Background()) // 创建可取消的上下文for i := 1; i <= 3; i++ {go worker(ctx, i)}time.Sleep(3 * time.Second) // 模拟主 Goroutine 的其他工作fmt.Println("Cancelling all workers...")cancel() // 发送取消信号time.Sleep(1 * time.Second) // 等待所有 Goroutine 退出fmt.Println("All workers stopped.")
}
输出:
Worker 1 is working...
Worker 2 is working...
Worker 3 is working...
...
Cancelling all workers...
Worker 1 stopped
Worker 2 stopped
Worker 3 stopped
All workers stopped.
解析:
context.WithCancel创建的上下文可以通过调用cancel()发送取消信号,从而优雅地停止所有子 Goroutine。
四、超时控制:WithTimeout 和 WithDeadline
1. 使用 WithTimeout 控制任务超时
示例:在 2 秒内完成任务,否则超时退出
package mainimport ("context""fmt""time"
)func worker(ctx context.Context) {select {case <-time.After(3 * time.Second): // 模拟长时间任务fmt.Println("Task completed")case <-ctx.Done(): // 接收超时信号fmt.Println("Task timed out")}
}func main() {ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) // 设置 2 秒超时defer cancel() // 确保资源释放go worker(ctx)time.Sleep(4 * time.Second) // 等待任务完成或超时
}
输出:
Task timed out
解析:
- 通过
context.WithTimeout创建的上下文,2 秒内未完成任务时自动发送取消信号。 - 超时上下文可避免 Goroutine 无限期运行,帮助更好地管理资源。
2. 使用 WithDeadline 设定截止时间
WithDeadline 和 WithTimeout 类似,只是使用具体的时间点来控制超时。
五、传递上下文中的数据:WithValue
有时,我们需要在多个 Goroutine 之间传递一些元数据。WithValue 允许我们将键值对存入上下文,并在子 Goroutine 中访问。
示例:传递用户信息
package mainimport ("context""fmt""time"
)func greetUser(ctx context.Context) {if user, ok := ctx.Value("user").(string); ok {fmt.Printf("Hello, %s!\n", user)} else {fmt.Println("No user found.")}
}func main() {ctx := context.WithValue(context.Background(), "user", "Alice") // 在上下文中存入用户信息go greetUser(ctx)time.Sleep(1 * time.Second) // 确保 Goroutine 执行完毕
}
输出:
Hello, Alice!
解析:
WithValue允许我们为上下文设置键值对,便于在多 Goroutine 间传递数据。
注意:
- 不建议用
WithValue传递重要的控制信息,例如取消信号或超时。
六、Context 的应用场景
- API 请求的超时控制:确保 HTTP 请求不会无限期等待。
- 任务取消:当用户主动取消某个操作时,通知相关的 Goroutine 停止工作。
- 传递元数据:例如在服务链路中传递用户身份、请求 ID 等信息。
七、完整示例:多任务协作控制
示例:启动多个任务,随时可取消所有任务
package mainimport ("context""fmt""sync""time"
)func worker(ctx context.Context, id int, wg *sync.WaitGroup) {defer wg.Done()for {select {case <-ctx.Done():fmt.Printf("Worker %d stopped\n", id)returndefault:fmt.Printf("Worker %d is processing...\n", id)time.Sleep(500 * time.Millisecond)}}
}func main() {var wg sync.WaitGroupctx, cancel := context.WithCancel(context.Background()) // 创建上下文for i := 1; i <= 3; i++ {wg.Add(1)go worker(ctx, i, &wg)}time.Sleep(2 * time.Second)fmt.Println("Cancelling all workers...")cancel() // 取消所有任务wg.Wait() // 等待所有任务完成fmt.Println("All workers stopped.")
}
输出:
Worker 1 is processing...
Worker 2 is processing...
Worker 3 is processing...
...
Cancelling all workers...
Worker 1 stopped
Worker 2 stopped
Worker 3 stopped
All workers stopped.
八、小结
- Context 用于并发控制:在 Goroutine 中传递取消信号、超时信号或携带元数据。
- 超时控制与资源管理:使用
WithTimeout和WithCancel及时终止任务,避免资源浪费。 - 多 Goroutine 协作:通过 Context 实现多个 Goroutine 之间的优雅通信。
相关文章:
Golang 并发编程:Context 包的使用与并发控制
文章目录 一、简介二、Context 的基本概念1. context 包常用函数 三、Context 的基本用法1. WithCancel:取消任务的上下文 四、超时控制:WithTimeout 和 WithDeadline1. 使用 WithTimeout 控制任务超时2. 使用 WithDeadline 设定截止时间 五、传递上下文…...
QGraphics类型学习使用【Qt】【C++】
QGraphics类型学习使用 需求过程全部完整代码 首先已知,QGraphicsView,QGraphicsScene, QGraphicsItem,分别称为:视图,场景,图元,图表就是各种各样的元素,图片元素,线条元…...
迁移学习和在线学习小结
迁移学习 英文小名: transform learning 简介: 把已经训练好的模型A为基本, 在新场景中, 根据新数据建立模型B 目的: 将某个领域或任务上学习到的知识/模式, 应用到不同但相关的领域/问题中 方法: 1.结构引用 适用情况: 新数据多, 场景相似度高, 可以基于原模型重新训练 2.特征…...
克里金插值(Kriging interpolation)
原理可参考该文件:克里金(Kriging)插值的原理与公式推导 - xg1990 matlab code可参考:Ordinary Kriging - File Exchange - MATLAB Central Some notes: 采用普通克里金时,采样的密度对结果影响非常大。若采样密度不够,误差会非…...
sealed class-kotlin中的封闭类
在 Kotlin 中,sealed class(密封类)是一种特殊的类,用于限制继承的类的数量。密封类可以被用来表示一组有限的类型,通常用于状态管理或表达多种可能的错误类型。 密封类用 sealed 关键字定义,这意味着只能…...
MongoDB Shell 基本命令(一)
MongoDB Shell 基本命令(一) 1. 基本概念 SQL术语/概念MongoDB术语/概念解释/说明databasedb数据库tablecollection数据库表/集合rowdocument数据记录行/文档columnfield数据字段/域indexindex索引table joins表连接,MongoDB不支持primary keyprimary key主键,Mon…...
Flink时间语义和时间窗口
前言 在实际的流计算业务场景中,我们会发现,数据和数据的计算往往都和时间具有相关性。 举几个例子: 直播间右上角通常会显示观看直播的人数,并且这个数字每隔一段时间就会更新一次,比如10秒。电商平台的商品列表&a…...
在wpf中登录成功之后怎么设置主页布局及点击不同的菜单跳转到不同的页面,这个是我们做wpf项目必要会的一个功能
通过frame与page实现在mvvm下的页面跳转 在wpf中登录成功之后怎么设置主页布局及点击不同的菜单跳转到不同的页面_哔哩哔哩_bilibili 1、MainWindow代码 <DockPanel><StackPanel DockPanel.Dock"Top" Height"40"><Grid><Grid.ColumnD…...
基于opencv的人脸闭眼识别疲劳监测
1. 项目简介 本项目旨在实现基于眼部特征的眨眼检测,通过监测眼睛开闭状态来计算眨眼次数,从而应用于疲劳监测、注意力检测等场景。使用了面部特征点检测算法,以及眼部特征比率(EAR, Eye Aspect Ratio)来判断眼睛的闭…...
aeo认证需要什么材料
AEO(Authorized Economic Operator)认证,即经认证的经营者认证,是企业信用管理体系的一种高级认证。申请AEO认证时,企业需要准备一系列的材料以证明其符合认证标准。以下是一份详细的AEO认证申请材料清单: …...
【iOS】YYModel
目录 什么是YYModel ? 如何使用YYModel ? 最简单的Model 与网络请求结合 属性为容器类的Model 白名单和黑名单 Model的嵌套 结语 什么是YYModel ? YYModel是一个用于 iOS 和 macOS 开发的高性能的模型框架,主要用于对象和…...
Cadence元件A属性和B属性相互覆盖
最近在使用第三方插件集成到Cadence,协助导出BOM到平台上,方便对BOM进行管理和修改,结果因为属性A和属性B不相同,导致导出的BOM错误。如下图: 本来我们需要导出Q12,结果给我们导出了Q13,或者反之&…...
【火山引擎】语音合成 | HTTP接口 | 一次性合成 | python
目录 一 准备工作 二 HTTP接口(一次性合成-非流式) 1 接口说明 2 身份认证 3 请求方式 三 实践 四 注意事项 火山引擎语音合成TTS(Text-to-Speech)是一种基于云计算的语音合成服务,可以将文本转化为自然、流畅的语音。以下是火山引擎TTS的主要功能和特点: ①多种语音…...
YOLOv11改进-卷积-空间和通道重构卷积SCConv
本篇文章将介绍一个新的改进模块——SCConv(小波空间和通道重构卷积),并阐述如何将其应用于YOLOv11中,显著提升模型性能。为了减少YOLOv11模型的空间和通道维度上的冗余,我们引入空间和通道重构卷积。首先,…...
记录一次从nacos配置信息泄露到redis写计划任务接管主机
经典c段打点开局。使用dddd做快速的打点发现某系统存在nacos权限绕过 有点怀疑是蜜罐,毕竟nacos这实在是有点经典 nacos利用 老规矩见面先上nacos利用工具打一波看看什么情况 弱口令nacos以及未授权访问,看这记录估计被光顾挺多次了啊 手动利用Nacos-…...
Unity加载界面制作
效果 UI部分 结构 说下思路: 因为是加载界面,所以最上层是一个Panel阻止所有的UI交互,这个Panel如果有图片就加一个图片,如果没有可以把透明度调到最大,颜色设为黑色. 下面最核心的就是一个进度条了,有图片的话,将进度条的底放进来,将进度条锚点设为下中,将滑动块的尺寸设为0.…...
最好的ppt模板网站是哪个?做PPT不可错过的18个网站!
现在有很多PPT模板网站,但真正免费且高质量的不多,今天我就分享主流的国内外PPT模板下载网站,并且会详细分析这些网站的优缺点,这些网站都是基于个人实际使用经验的,免费站点会特别标注,让你可以放心下载&a…...
煤矿安全监测监控作业题库
第一部分 安全法律法规知识子题库 单选题 1.《安全生产法》规定,生产经营单位应当向从业人员如实告知作业场所和工作岗位存在的(A)、防范措施以及事故应急措施。 A. 危险因素 B. 人员状况 C. 设备状况 D. 环境状况 2.《安全生产法》规定&…...
【记录】Django数据库的基础操作
数据库连接 在Django中使用 mysqlclient 这个包用于数据库的连接,切换至 Django环境中直接 pip install mysqlclient 安装此包 1 数据库连接配置 在项目目录下的setting.py中配置 DATABASES {default: {ENGINE: django.db.backends.mysql,NAME: mini,#数据库名US…...
XHCI 1.2b 规范摘要(五)
系列文章目录 XHCI 1.2b 规范摘要(一) XHCI 1.2b 规范摘要(二) XHCI 1.2b 规范摘要(三) XHCI 1.2b 规范摘要(四) XHCI 1.2b 规范摘要(五) 文章目录 系列文章目…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
