Golang并发控制的三种方案

Channel

Channel是Go在语言层面提供的一种协程间的通信方式,我们可以通过在协程中向管道写入数据和在待等待的协程中读取对应协程的次数来实现并发控制。

func main() {intChan := make(chan int, 5)waitCount := 5for i := 0; i < waitCount; i++ {go func() {intChan <- 1}()}for i := 0; i < waitCount; i++ {<-intChan}fmt.Println("主进程结束")
}

WaitGroup

waitgroup通常应用于等待一组“工作协程”结束的场景,waitgroup底层是由一个长度为3的数组实现的,其内部有两个计数器,一个是工作协程计数器、一个是坐等协程计数器,还有一个是信号量。工作协程全部运行结束后,工作协程计数器将置为0,会释放对应坐等协程次数的信号量。

两点注意:

  1. Add()方法中的参数大小要于工作协程的数量相等,否则会导致坐等协程一直等待,触发死锁panic

  2. Done()方法执行的次数要与Add()方法中的工作协程计数器的数量一致,否则当工作协程计数器<0时,会触发panic【panic: sync: negative WaitGroup counter】

func main() {wg := sync.WaitGroup{}wg.Add(2)go func() {time.Sleep(3 * time.Second)fmt.Println("等待三分钟的协程结束了")wg.Done()}()go func() {time.Sleep(3 * time.Second)fmt.Println("等待三分钟的协程结束了")wg.Done()}()wg.Wait()
}

Context

适用于一个协程派生出多个协程的情况,可以控制多级的goroutine。我们可以通过一个Context对象,对派生出来的树状goroutine进行统一管理,并且每个goroutine具有相同的上下文。做统一关闭操作、统一定时关闭、统一传值的操作。多个上下文协程之间可以互相嵌套配合。

golang实现了四种原生的上下文对象

  • emptyCtx: 该上下文对象一般是作为父节点的,如果没有父节点,我们通常使用context.Background()方法来获取emptyCtx对象,并将其作为创建其他节点的父节点。

  • cancelCtx: 该上下文对象可以关闭所有拥有同一个上下文的goroutine,通过在子协程中监听cancelCtx.Done方法,来结束所有的派生协程。具体代码看下方,我们通过WithCancel()方法来获取该对象。

  • timerCtx:该上下文对象是对cancelCtx对象的进一步封装,比cancelCtx主动关闭之外,多了了一个定时关闭功能。我们可以通过WithTimeout()和WithDeadline()这两种方法来获取该对象。其中WithTimeout()和WithDeadline()这两种方法点是WithTimeout()是设置过一段时间关闭上下文,WithDeadline()是设置那一个时间点来关闭这一个上下文。

  • valueCtx:该上下文对象并不用于进行协程的控制,而是在多级协程之间进行值得传递,方便共享一些相同得上下文内容。

以上除emptyCtx外的上下文对象和获取实例的方法如下图所示:

 Context示例代码

  • cancelCtx

        我们在所有的派生协程中传入相同的cancelContext对象,并在每一个子协程中使用switch-case结构监听上下文对象是否关闭,如果上下文对象关闭了,ctx.Done()返回的管道就可以读取到一个元素,使所在的case语句可执行,之后退出switch结构,执行协程中的其他代码。

func main() {ctx, cancelFunc := context.WithCancel(context.Background())deadline, ok := ctx.Deadline()fmt.Println(deadline, ok)done := ctx.Done()fmt.Println(reflect.TypeOf(done))fmt.Println(done)go HandelRequest(ctx)//<-done 阻塞当前一层的goroutinetime.Sleep(5 * time.Second)fmt.Println("all goroutines is stopping!")cancelFunc()err := ctx.Err()fmt.Println(err) //context canceledtime.Sleep(5 * time.Second)
}func HandelRequest(ctx context.Context) {go WriteMysql(ctx)go WriteRedis(ctx)for {select {case <-ctx.Done():fmt.Println("HandelRequest Done")returndefault:fmt.Println("等一等,Handler正在执行中")time.Sleep(2 * time.Second)}}
}func WriteRedis(ctx context.Context) {for {select {case <-ctx.Done():fmt.Println("WriteRedis Done.")returndefault:fmt.Println("等一等,Redis正在执行中")time.Sleep(2 * time.Second)}}
}func WriteMysql(ctx context.Context) {for {select {case <-ctx.Done():fmt.Println("WriteMysql Done.")returndefault:fmt.Println("等一等,Mysql正在执行中")time.Sleep(2 * time.Second)}}
}
  • timerCtx

        这里代码以WithTimeout举例,相比与我们之前的手动调用关闭,使用timerCtx定时上下文对象后,可以是实现到达指定的时间自动进行关闭的操作。

func main() {deadline, _ := context.WithTimeout(context.Background(), 5*time.Second)go HandelRequest(deadline)time.Sleep(10 * time.Second)}func HandelRequest(ctx context.Context) {go WriteMysql(ctx)go WriteRedis(ctx)for {select {case <-ctx.Done():fmt.Println("HandelRequest Done")returndefault:fmt.Println("等一等,Handler正在执行中")time.Sleep(2 * time.Second)}}
}func WriteRedis(ctx context.Context) {for {select {case <-ctx.Done():fmt.Println("WriteRedis Done.")returndefault:fmt.Println("等一等,Redis正在执行中")time.Sleep(2 * time.Second)}}
}func WriteMysql(ctx context.Context) {for {select {case <-ctx.Done():fmt.Println("WriteMysql Done.")returndefault:fmt.Println("等一等,Mysql正在执行中")time.Sleep(2 * time.Second)}}
}
  • valueCtx

        我们可以通过嵌套WithValue上下文,来进行多个key-value在派生协程中传递,共享常量

func main() {ctx, cancelFunc := context.WithCancel(context.Background())value1 := context.WithValue(ctx, "param1", 1)value2 := context.WithValue(value1, "param2", 2)go ReadContextValue(value2)time.Sleep(10 * time.Second)cancelFunc()time.Sleep(5 * time.Second)
}func ReadContextValue(ctx context.Context) {fmt.Println(ctx.Value("param1"))fmt.Println(ctx.Value("param2"))
}

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

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

相关文章

上海SNEC光伏展参展总结--安科瑞

安科瑞戴婷 Acrel-Fanny 今年的snec上海光伏展吸引了来自全球各地的光伏行业专业人士及爱好者&#xff0c;本次展会共有来自30多个国家和地区的超过2000家企业参展&#xff0c;展出的光伏产品涵盖了太阳能电池、太阳能组件、逆变器、太阳能辅助设备等众多领域。 随着近年来光…

《收获,不止oracle》读书笔记一:oracle体系结构

从图中可以看出,oracle数据库是由实例和一组数据库文件组成。实例是由oracle开辟的内存区和一组后台进程组成的。

2024.6.18

Python的网络编程 网络四层 在开始前,我们需要先了解一下我们在网络通信过程中的四个层次 我们上网产生的数据都是经过协议栈一层一层的封装然后经网卡发送到网络&#xff0c;经网络发送到服务端&#xff0c;然后服务端又是一层一层的解封装拿到自己想要的数据。 我们学习的…

YOLOv8目标检测算法在地平线Bernoulli2架构BPU上高效部署参考(PTQ方案)30fps!

—— 以RDK X3为例&#xff0c;修改Head部分&#xff0c;8ms疾速Python后处理程序&#xff0c;30fps稳稳当当 本文在地平线对YOLOv8s的Backbone修改的基础上&#xff0c;提出一种在地平线Bernoulli2架构BPU上部署YOLOv8的后处理思路。使用640640分辨率&#xff0c;80类别基于C…

香橙派AIPro开机测试

资料准备&#xff1a; 香橙派官网资料下载链接&#xff1a;http://www.orangepi.cn/html/hardWare/computerAndMicrocontrollers/service-and-support/Orange-Pi-AIpro.html 硬件准备 香橙派ai pro一个 32G sd卡&#xff0c;带出厂镜像 电源 鼠标 键盘 hdmi显示屏 测试介绍 由…

4418 android4.4 + 6818 android5.1 移植gps

网上已经有的移植的资料 目前 3399 的板子上 对已有的可运行的GPS 进行测试。 我这里的 rk3399 的板卡 , Android7 Android8 都是 可以运行 GPS 应用程序的。 使用的是 ttyS4 的节点。 问题: 我发现, 开机就删掉 ttyS4 节点,也是可以 打开应用的。并且可以正常运行。不…

图片怎么弄成黑白的?关于将图片改成黑白的几种方法

图片怎么弄成黑白的&#xff1f;黑白照片以其独特的艺术魅力和经典的视觉效果&#xff0c;依然在摄影和图像处理中占据重要地位。无论是为了追求怀旧的氛围&#xff0c;还是为了突出图像的构图和光影效果&#xff0c;许多人都希望将彩色图片转换成黑白图片。这不仅可以赋予图像…

全网最强Spring教程 | 万字长文爆肝Spring(三)

Spring_day03 今日目标 理解并掌握AOP相关概念能够说出AOP的工作流程能运用AOP相关知识完成对应的案例编写重点掌握Spring的声明式事务管理 1&#xff0c;AOP简介 前面我们在介绍Spring的时候说过&#xff0c;Spring有两个核心的概念&#xff0c;一个是IOC/DI&#xff0c;一个…

影响建筑效果图后期时间的因素有哪些?渲染100邀请码1a12

建筑效果图是建筑设计师展示设计方案的重要手段&#xff0c;为了完美展现&#xff0c;我们通常会对效果图进行后期处理&#xff0c;那么影响后期时间的因素有哪些&#xff1f;这次我们来看看吧。 1、底图的质量 底图是指原始的渲染图片&#xff0c;它决定了后期处理的难易程度…

鸿蒙APP开发的技术难点

鸿蒙APP开发的技术难点主要体现在以下几个方面&#xff0c;鸿蒙APP开发是一项技术难度较高的工作&#xff0c;需要开发者具备扎实的编程基础、分布式开发能力和学习新技术的意愿。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1. 多…

软件生存期模型

软件生存期模型是为了获得高质量软件所需要完成的一系列任务的框架&#xff0c;它规定了完成各项任务的工作步骤。典型的软件生存期模型有瀑布模型、增量模型、快速原型模型、喷泉模型、螺旋模型、统一过程、敏捷开发模型等。 瀑布模型 1970年由Royce首先提出瀑布模型&#x…

老杨说运维 | 如何结合现状进行运维路径建设(文末附演讲视频)

青城山脚下的滔滔江水奔涌而过&#xff0c;承载着擎创一往无前的势头&#xff0c;共同去向未来。2024年6月&#xff0c;双态IT成都用户大会擎创科技“数智化可观测赋能双态运维”专场迎来了完满的收尾。 本期回顾来自擎创科技CTO葛晓波的现场演讲&#xff1a;数智化转型的核心目…

超多细节—app图标拖动排序实现详解

前言&#xff1a; 最近做了个活动需求大致类似于一个拼图游戏&#xff0c;非常接近于咱们日常app拖动排序的场景。所以想着好好梳理一下&#xff0c;改造改造干脆在此基础上来写一篇实现app拖动排序的文章&#xff0c;跟大家分享下这个大家每天都要接触的场景&#xff0c;到底…

超图论文细品——2019年AAAI《Hypergraph Neural Networks》

我是“导航” 1 摘要1.1 简介1.2 问题描述 2 超图2.1 图和超图对比 参考 1 摘要 1.1 简介 文章提出了一种名为超图神经网络的框架&#xff0c;用于高维数据的表示学习。 该方法英文称呼为 Hypergraph Neural Networks&#xff0c;简写为 HGNN。 1.2 问题描述 传统的 GNN 是…

SD卡可以格式化成NTFS吗 SD卡Mac怎么读取内容

SD卡作为便携式存储媒介&#xff0c;广泛应用于我们的日常生活与工作之中。而NTFS&#xff0c;作为一种先进的文件系统&#xff0c;因其强大的功能和安全性&#xff0c;在Windows平台备受青睐。然而&#xff0c;当谈及将SD卡格式化为NTFS这一话题时&#xff0c;用户的疑惑随之而…

Jetpack Compose_Alignment对其+Arrangement排列

文章目录 1.Alignment 对齐1.1Alignment 对齐方式1.2AbsoluteAlignment 绝对对齐1.3BiasAlignment 偏差对齐1.4BiasAbsoluteAlignment偏差绝对对齐 2.Arrangement 排列2.1Arrangement 排列方式2.2Arrangement.Horizontal2.3Arrangement.Vertical 1.Alignment 对齐 1.1Alignmen…

Uncaught TypeError: Cannot read properties of null (reading ‘isCE‘)

问题描述 使用 view-ui-plus 加 vue3 开发项目&#xff0c;本地启动项目正常&#xff0c;但其他人将代码拉下来&#xff0c;启动项目时报错 Uncaught TypeError: Cannot read properties of null (reading isCE)&#xff1a; 原因分析&#xff1a; 尝试将 mode_nodules 文件删…

C# yolov8 OpenVINO 同步、异步接口视频推理

C# yolov8 OpenVINO 同步、异步接口视频推理 目录 效果 项目 代码 下载 效果 同步推理效果 异步推理效果 项目 代码 using OpenCvSharp; using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using System.Windows.Form…

智源更新大模型排行榜:豆包大模型“客观评测”排名国产第一

6月中旬&#xff0c;智源研究院旗下的 FlagEval 大模型评测平台发布最新榜单&#xff1a;在有标准答案的“客观评测”中&#xff0c;GPT-4 以76.11分在闭源大模型中排名第一&#xff1b;Doubao-Pro&#xff08;豆包大模型&#xff09;以75.96分排名第二&#xff0c;同时也是得分…

隧道代理是什么?怎么运作的?

隧道代理作为网络代理的一种形式&#xff0c;已经在现代互联网世界中扮演着重要的角色。无论是保护隐私、访问受限网站还是实现网络流量的安全传输&#xff0c;隧道代理都发挥着重要作用。在本文中&#xff0c;我们将深入探讨隧道代理的概念、运作方式以及在不同场景中的应用。…