原子操作和杀死goroutine两种方法,解决多协程调用同一个函数的问题
文章目录
- 1. 问题描述
- 2. 解决方案
- 方案1——原子读写(推荐)
- 解决方案
- 代码实现
- 方案2——杀死goroutine
- 解决方案
- 缺点
- 代码实现
1. 问题描述
实际开发中遇见这样一个问题,在此记录一下:
Go多协程持续运行每3s读取一次数据过程中出现错误,此时多个协程同时报错(假设有3个协程),对该错误的处理方法被封装到了函数handleError()中,因此3个协程同时将错误抛给了handleError()。handleError()中3个协程同时处理同一个问题后,返回原来的函数重新执行。
此时有3个协程调用原来的函数。而这里我只希望有一个协程调用该函数。为什么只希望一个协程调用该函数呢?原因如下:
1)如果我是用handleError1()来处理错误,那么3个协程重新运行example函数后将结束运行,不能满足我持续运行读取数据的要求。
2)如果用handleError2()处理错误,那么3个协程,每个协程又调用3个子协程,加上主协程,将一共有9个协程重复读数据,不满足要求。
func main() {for i := 0; i < 3; i++ {go example(i)}
}func example (i int) {// ...if err != nil {handleError(i)}
}func handleError1(i int) {// ...example(i)
}func handleError2(i int) {// ...for i := 0; i < 3; i++ {go example(i)}
}
3)如果把for循环放到example中,多协程运行其中的匿名函数,如下所示,则会出现和上述2)一样的问题,出现9个协程。
func main() {go example(i)
}func example (i int) {for i := 0; i < 3; i++ {// 多协程运行匿名函数go func (i int) {// ...if err != nil {handleError(i)}}(i)}
}func handleError(i int) {// ...example(i)
}
2. 解决方案
方案1——原子读写(推荐)
解决方案
设置一个全局变量,用于判断有多少个goroutine报错,读到报错的goroutine时,将变量加1。只有当变量为1时才处理错误,大于1时不处理错误。这样就能保证只处理一个goroutine的错误了。
注意:这里的数值读取必须是原子性的,否则会造成多个goroutine同时处理该数据的情况。
代码实现
var errNum int32
func main() {for i := 0; i < 3; i++ {go example(i)}
}func example (i int) {// ...if err != nil {atomic.AddInt32(&errNum, 1)if atomic.LoadInt32(&errNum) == 1 {handleError(i)}}
}func handleError(i int) {// ...atomic.SwapInt32(&errNum, 0)for i := 0; i < 3; i++ {go example(i)}
}
方案2——杀死goroutine
解决方案
发现有goroutine报错时查看当前goroutine数量,直接杀掉所有其他goroutine,只保留主goroutine和报错goroutine。
缺点
其他goroutine可能没有报错,这时直接杀掉其他goroutine这种一刀切的方法十分暴力且不明智。
代码实现
这里for循环放在函数example()内外的两种方式都可以,不影响功能。这里只用第一种方式举例实现。
注意:保证goroutine数量为2的时候调用handleError(),1个goroutine是主协程,1个goroutine是那3个子协程中的1个,负责调用handleError()。
func main() {for i := 0; i < 3; i++ {go example(i)}
}func example (i int) {// ...if err != nil {for runtime.NumGoroutine() != 2 {runtime.Goexit()}handleError(i)}
}func handleError(i int) {// ...for i := 0; i < 3; i++ {go example(i)}
}
原子操作和杀死goroutine两种方法,解决多协程调用同一个函数的问题相关推荐
- qmenu只在鼠标单击时消失_两种方法解决win10电脑无法使用无线鼠标问题
使用有线鼠标时用户们是否也都会被那条线控制住,有时需要大范围移动时并不行,现在很多用户都会选择使用无线鼠标,因为可以随意移动使用更加方便.但是在使用中也有用户遇到了麻烦,使用win10连接鼠标后无法使 ...
- cf服务器断开连接出现信息有误,CF与服务器断开连接是什么原因?两种方法解决...
穿越火线每次玩到高分的时候游戏就会被提示:"网络出现异常,与服务器断开连接"的情况,怎么解决? 方法步骤: 第一种方法: 1.在电脑上下载安装360安全卫士,接着在主界面中找到工具 ...
- python两种方法解决线程冲突问题
本博文源于python基础炫酷技能,主要讲述python的线程的问题.大家学到多线程的时候只要搞明白两种东西即可,第一线程通信,另一个叫做线程冲突.本博文就以一种打印数字的方法浅析线程冲突的解决方案! ...
- php数组比对算法,php学习之两种方法使用比较数组差异的array_diff()函数
本篇文章将简单介绍php比较两个数组的差异array_diff()函数,感兴趣的朋友可以了解一下. php内置函数中有一个array_diff():意思比较两个数组的键值,并返回差集. 下面是通过数组 ...
- 两种方法解决pip、conda安装库时慢的问题
方法一: 直接用国内的源,比如清华源,但清华源有时不太好用,我现在大都用百度源 pip install 库名称 -i https://mirror.baidu.com/pypi/simple 方法二: ...
- 两种方法解决口算练习题
文章目录 口算练习题 题目描述 输入格式 输出格式 样例 #1 样例输入 #1 样例输出 #1 提示 题解: 大佬的代码: 口算练习题 题目描述 王老师正在教简单算术运算.细心的王老师收集了i道学生经 ...
- oracle 0.5格式问题,两种方法解决Oracle的数值0.5只显示成.5问题
Oracle对数值0.n转换成char类型的时候会自动忽略前面的0(原因好像是为了节省空间0.5保存到数据库为.5).例如: SQL> SELECT to_char(0.5) FROM DUAL ...
- 两种方法解决腾讯会议独立显卡占用高的问题
适用场景:只参与会议,观看他人屏幕共享. 方法一: 如果是英伟达独立显卡: ①打开 "NVIDIA控制面板" ②打开 "管理3D设置" ③添加 "腾讯 ...
- 两种方法解决Ubunto不能挂载u盘问题 Error mounting /dev/sdc1 at /media/pc01/U盘: Command-line `mount -t “exfat“ -o “
Ubuntu 电脑下插入移动硬盘,显示不能挂载该硬盘 报错: Error mounting /dev/sdc1 at /media/pc01/兰科芯 U盘: Command-line `mount - ...
最新文章
- 使用脑电图慢皮层电位重建3D空间中的手,肘和肩的实际和想象的轨迹
- windows中以管理员身份运行cmd
- 网关限流(令牌桶算法)
- 什么是 Freeview Play
- django高级应用(分页功能)
- 【习题 6-5 UVA-1600】Patrol Robot
- JQuery 实战第三讲:绚丽菜单
- win7系统关闭蓝牙服务器,Win7系统怎么关闭蓝牙功能
- 在线制作FLASH,图片的网站集合
- 基于Java实现的迷宫小游戏
- linux判断三个数大小程序,几个shell程序设计小知识(shell常识部分)
- “英制长度单位”的由来
- 计量经济学术语(转载)
- 参考爆料英特尔i5-10400f和i5-10400区别?哪个好?深度爆料评测
- Revit快速标注 | 有求必应的【万能标注】操作步骤
- 安装npm cnpm方法
- PS网页设计教程XXIII——创建一个售卖iPhone 5应用程序的网站
- 【搜索+DP】codevs1066-引水入城
- 基于微信小程序的学生社团管理系统
- 想学编程要些啥基础?
热门文章
- win10电脑浏览器哪个好_电脑WinXP、Win7和Win10,哪个操作系统最好用?
- Pyqt5 多标签_不要乱用OmniFocus的标签
- python怎样打开加密的文件_如何使用python加密多个文件
- c语言的课本答案,c语言课本试题答案
- json字符串转成formdata_FormData 数据转化为 json 数据
- python三维数据增强_python图像数据增强——imgaug (三)
- python程序设计教程上海交通大学_上海交通大学 python程序设计课程PPT Ch2.ppt
- HTTPS协议详解:TLS/SSL握手过程
- python字符串,列表常用操作
- Java中的Instanceof