记一次Goroutine与wg导致的问题
前言
今天发现了一个问题是之前一直没有注意到的,这里记一下
正文
Send Closed Chan
问题概述
代码逻辑是启动时启动多个 channel, channel1 获取数据监听数据处理后发送给 channel2 , channel2 处理后再给 channel3 等等
在 channel1 写完数据后将通道 channel1 关闭, channel1 关闭后 channel2 也关闭, 达到任务执行完毕后通道全部关闭的效果
我之前的代码是
func StartVerify() {
wg := sync.WaitGroup{}
for {
data, ok := <-TypicalResChan
if !ok {
wg.Wait()
close(VerifyBossDNSChan)
break
}
go func() {
wg.Add(1)
ok := Verify(data)
if ok {
VerifyBossDNSChan <- data
}
wg.Done()
}()
}
}
后来使用中发现有时候会报 send closed channel 的错误,大佬看了一眼就发现了问题
问题剖析
就以上面的举例, 上游向 TypicalResChan 发送数据时, 如果不是 close 请求, 会启动一个 goroutine 去处理逻辑, 而在 启动这个 goroutine 后在内部进行 wg 的 Add 注册, 注意这个过程是有耗时的, 所以问题来了, 当上游向 TypicalResChan 发送 close 时, 进入 !ok 的逻辑, 此时等待 wg 释放, 此时有可能上一个数据接收到后还在启动一个 goroutine ,还没有 Add注册, 此时wg没有监听到这个 goroutine 的注册, 造成不会等待这个 goroutine ,直接就关闭了 TypicalResChan, 而这个 goroutine 执行后向 TypicalResChan 发送数据时 TypicalResChan 已经关闭, 所以会报错导致 panic
另外, 还需要注意的是在 wg 没有注册前就 wait 是不推荐的, 很容易出现问题
还有就是判断通道关闭更推荐使用 range 省去判断 !ok 的步骤保持代码整洁
问题解决
修改成这样即可
func StartVerify() {
wg := sync.WaitGroup{}
for data := range TypicalResChan {
wg.Add(1)
go func(data Result) {
defer wg.Done()
ok := Verify(data)
if ok {
VerifyBossDNSChan <- data
}
}(data)
}
wg.Wait()
close(VerifyBossDNSChan)
}
在上游 close 时 range 会自动结束, 而受到正常数据先 Add 防止时间差导致的 Add 失败问题, 在 1.14 后 go 优化了 defer 的逻辑, defer 基本不再有消耗, 所以推荐使用 defer 注册 wg 的关闭, 而在 close 时, for 循环结束, wg 在 wait 后再 close
记一次Goroutine与wg导致的问题的更多相关文章
- 记一次因证书问题导致请求失败问题SSLHandshakeException
记一次因证书问题导致请求失败问题SSLHandshakeException 转载请注明出处:https://www.cnblogs.com/funnyzpc/p/10989813.html 最近接一外 ...
- 捉虫记(四)线程安全导致的HighCpu
一个朋友QQ群里说网站启动后会cpu很高,想要帮忙看一下dump. 1.打开windbg加载dump文件后第一个命令lmf,这个命令显示加载的dll以及路径,这样子可以找个dll来帮忙加载sos,(额 ...
- 记因PHP的内存溢出导致的事故之解决
如果对您有用记得关注,更多干货. 今天上午刚到公司,就有同事在公司群里反映某个计划任务出现问题了.我就怀着刨根问底的心,去查看了log.发现挺有意思的一个问题,PHP内存溢出导致脚本执行失败.那就一起 ...
- 记一次IIS发布网站导致系统时常跳入登录页面的问题解决
服务器:winserver2012R2 iis 发布网站后,正常浏览网页,时常跳到登录页面,第一反应session过期,因为登录信息都存在session,但session 都是默认配置过期时间为20分 ...
- 飞机找不到,流量哪去了?记一次移动WAP网关导致的问题
这几天随着客户端一个新版本发布,运维发现CDN的流量猛跌: 话说流量就是金钱,流量就是工资.领导很生气,后果很严重.没什么好说的,赶紧查!一开始怀疑服务端有问题,先受伤的总是我们,当然这也是没错的,因 ...
- 记一次JPA查询分页导致的数据丢失问题
使用JPA查询,共17条数据,每页10条数据. 第一页与第二页有一条重复的数据,导致丢失一条数据 后查明原因发现,该查询使用了排序,排序字段的值在多条数据中相同,比如在3-11条是相同的值.此时跳到第 ...
- 记一次内存无法回收导致频繁fullgc机器假死的思路
确定挂机 络绎不绝的来不同类型的bug 当bug滚滚而来时,不要怀疑,你的发布的应用基本是不可用状态了.观察哨兵监控数据,特别是内存打到80%基本就挂机了,或者监控数据缺失也基本是挂机了.此时应当马上 ...
- 记-ItextPDF+freemaker 生成PDF文件---导致服务宕机
摘要:已经上线的项目,出现服务挂掉的情况. 介绍:该服务是专门做打印的,业务需求是生成PDF文件进行页面预览,主要是使用ItextPDF+freemaker技术生成一系列PDF文件,其中生成流程有:解 ...
- 记一次Apache的代码导致生产服务耗时增加
引言 二狗:二胖快醒醒,赶紧看看刚才报警邮件,你上次写的保存用户接口耗时(<二胖的参数校验坎坷之路>)大大上升,赶紧排查下原因. 二胖:好的,马上看,内心戏可十足(心里却在抱怨,大中午的搅 ...
随机推荐
- 6、Sping Cloud Feign
1.Spring Cloud Feign简介 (1).Fegin简介 官方文档:http://projects.spring.io/spring-cloud/spring-cloud.html#spr ...
- 题解-CF1389F Bicolored Segments
题面 CF1389F Bicolored Segments 给 \(n\) 条线段 \([l_i,r_i]\),每条有个颜色 \(t_i\in\{0,1\}\),求最多选出多少条线段,使没有不同颜色的 ...
- 配置nginx支持THINKPHP的PATH_INFO
ThinkPHP支持通过PATHINFO和URL rewrite的方式来提供友好的URL,但是Nginx中默认是不支持PATHINFO的,所以我们需要修改nginx.conf文件. location ...
- Pytest 系列(27)- allure 命令行参数
如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html 先看看 allure 命令的帮助文 ...
- 精尽Spring MVC源码分析 - WebApplicationContext 容器的初始化
该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...
- Linux下keepalived配置
1.背景 节点1:192.168.12.35 节点2:192.168.12.36 2.keepalived安装 使用yum仓库安装keepalived [root@node01 ~]# yum ins ...
- AWT05-对话框
1.Dialog Dialog组件是Window的子类,是容器类,是特殊组件. Dialog是可以独立存在的顶级窗口,使用上和普通窗口几乎没有区别,但应注意以下两点: 1.对话框通常依赖于其他窗口,也 ...
- Flink读写Redis(一)-写入Redis
项目pom文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w ...
- angular8 页面滚动到某一个特定位置
背景:使用angular8安装的 Fuse-v8.0.0-demo 后台的框架 锚点: id='nearby' 流程:无论是点击触发方法也好,还是直接调用方法也好,这里只写 引入: import {C ...
- ⑦SpringCloud 实战:引入Sleuth组件,完善服务链路跟踪
这是SpringCloud实战系列中第7篇文章,了解前面第两篇文章更有助于更好理解本文内容: ①SpringCloud 实战:引入Eureka组件,完善服务治理 ②SpringCloud 实战:引入F ...