文章目录

  • 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两种方法,解决多协程调用同一个函数的问题相关推荐

  1. qmenu只在鼠标单击时消失_两种方法解决win10电脑无法使用无线鼠标问题

    使用有线鼠标时用户们是否也都会被那条线控制住,有时需要大范围移动时并不行,现在很多用户都会选择使用无线鼠标,因为可以随意移动使用更加方便.但是在使用中也有用户遇到了麻烦,使用win10连接鼠标后无法使 ...

  2. cf服务器断开连接出现信息有误,CF与服务器断开连接是什么原因?两种方法解决...

    穿越火线每次玩到高分的时候游戏就会被提示:"网络出现异常,与服务器断开连接"的情况,怎么解决? 方法步骤: 第一种方法: 1.在电脑上下载安装360安全卫士,接着在主界面中找到工具 ...

  3. python两种方法解决线程冲突问题

    本博文源于python基础炫酷技能,主要讲述python的线程的问题.大家学到多线程的时候只要搞明白两种东西即可,第一线程通信,另一个叫做线程冲突.本博文就以一种打印数字的方法浅析线程冲突的解决方案! ...

  4. php数组比对算法,php学习之两种方法使用比较数组差异的array_diff()函数

    本篇文章将简单介绍php比较两个数组的差异array_diff()函数,感兴趣的朋友可以了解一下. php内置函数中有一个array_diff():意思比较两个数组的键值,并返回差集. 下面是通过数组 ...

  5. 两种方法解决pip、conda安装库时慢的问题

    方法一: 直接用国内的源,比如清华源,但清华源有时不太好用,我现在大都用百度源 pip install 库名称 -i https://mirror.baidu.com/pypi/simple 方法二: ...

  6. 两种方法解决口算练习题

    文章目录 口算练习题 题目描述 输入格式 输出格式 样例 #1 样例输入 #1 样例输出 #1 提示 题解: 大佬的代码: 口算练习题 题目描述 王老师正在教简单算术运算.细心的王老师收集了i道学生经 ...

  7. oracle 0.5格式问题,两种方法解决Oracle的数值0.5只显示成.5问题

    Oracle对数值0.n转换成char类型的时候会自动忽略前面的0(原因好像是为了节省空间0.5保存到数据库为.5).例如: SQL> SELECT to_char(0.5) FROM DUAL ...

  8. 两种方法解决腾讯会议独立显卡占用高的问题

    适用场景:只参与会议,观看他人屏幕共享. 方法一: 如果是英伟达独立显卡: ①打开 "NVIDIA控制面板" ②打开 "管理3D设置" ③添加 "腾讯 ...

  9. 两种方法解决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 - ...

最新文章

  1. 使用脑电图慢皮层电位重建3D空间中的手,肘和肩的实际和想象的轨迹
  2. windows中以管理员身份运行cmd
  3. 网关限流(令牌桶算法)
  4. 什么是 Freeview Play
  5. django高级应用(分页功能)
  6. 【习题 6-5 UVA-1600】Patrol Robot
  7. JQuery 实战第三讲:绚丽菜单
  8. win7系统关闭蓝牙服务器,Win7系统怎么关闭蓝牙功能
  9. 在线制作FLASH,图片的网站集合
  10. 基于Java实现的迷宫小游戏
  11. linux判断三个数大小程序,几个shell程序设计小知识(shell常识部分)
  12. “英制长度单位”的由来
  13. 计量经济学术语(转载)
  14. 参考爆料英特尔i5-10400f和i5-10400区别?哪个好?深度爆料评测
  15. Revit快速标注 | 有求必应的【万能标注】操作步骤
  16. 安装npm cnpm方法
  17. PS网页设计教程XXIII——创建一个售卖iPhone 5应用程序的网站
  18. 【搜索+DP】codevs1066-引水入城
  19. 基于微信小程序的学生社团管理系统
  20. 想学编程要些啥基础?

热门文章

  1. win10电脑浏览器哪个好_电脑WinXP、Win7和Win10,哪个操作系统最好用?
  2. Pyqt5 多标签_不要乱用OmniFocus的标签
  3. python怎样打开加密的文件_如何使用python加密多个文件
  4. c语言的课本答案,c语言课本试题答案
  5. json字符串转成formdata_FormData 数据转化为 json 数据
  6. python三维数据增强_python图像数据增强——imgaug (三)
  7. python程序设计教程上海交通大学_上海交通大学 python程序设计课程PPT Ch2.ppt
  8. HTTPS协议详解:TLS/SSL握手过程
  9. python字符串,列表常用操作
  10. Java中的Instanceof