为了账号安全,请及时绑定邮箱和手机立即绑定

golang 并发问题

golang 并发问题

慕莱坞森 2019-05-11 09:39:37
allMap存储的是一个任务列表,KEY标记了这个任务类型,Value对应的是任务的参数,现在我需要并发处理这些任务。开发过程中使用了如下两种方法,效果并不好,感觉自己没有领会到golang并发处理的思想;下面是我的几点体会和疑惑,希望得到各位大神的指导。方式一//allMap中存储了任务列表//Task定义如下typeTaskstruct{Paramsinterface{}ResultChanchan[]byte//Wg*sync.WaitGroup}Params是参数,ResultChan是处理完毕之后,将结果写入到ResultChan中;//并发处理任务forkey,value:=rangeallMap{gofunc(kstring,vinterface{}){log.Debug("k:",k)ifk==tools.REQUEST_BAOJIE{//Alog.Debug("baojieelemlen:",len(value))one_task=&service.Task{Params:v,ResultChan:make(chan[]byte,len(value)),//Wg:new(sync.WaitGroup),}//Blog.Debugf("1one_task:%+v",one_task)//AddTask函数逻辑会处理one_task,处理完毕之后,将结果写入到one_task结构体的ResultChan字段;service.AddTask(one_task)}elseifk==tools.REQUEST{}}(key,value)}//Clog.Debugf("2one_task:%+v",one_task)//接收结果gofunc(){foritem:=rangeone_task.ResultChan{log.Debug("ReceivedataFromResultChan:",string(item))}log.Debug("Process",tools.REQUEST_BAOJIE,"end")}()这种方式的弊端,太依赖程序执行的先后顺序了,测试的过程中,发现当C发生在A和B之前时,会使接收结果goroutinue访问ResultChan成员发生奔溃,因为此时ResultChan还没有申请空间。方案一解决方案:service.AddTask(one_task)函数再加一个参数,chan
查看完整描述

2 回答

?
胡说叔叔

TA贡献1804条经验 获得超8个赞

想太多了,怕同时起多了协程,可以定义协程长度,更甚至采用协程池。简单写个实现:
typetaskstruct{
namestrig
paramsinterface{}
result[]byte
}
vargt=make(chanint,10)//同时只允许10个task一起执行
vartkr=make(chantask,10)
gofunc(){
for_,t:=rangeallTaskMap{
gt<-1
gofunc(curtasktask){
//处理task,
tkr<-curtask//处理完,可以使用channel将结果传输出去
<-gt//处理完毕退出
}(t)
}
}()
for{
select{
casert:=<-tkr:
//处理结果
}
}
实际上很少用map去存储task列表,可以考虑使用channel传入task
                            
查看完整回答
反对 回复 2019-05-11
  • 2 回答
  • 0 关注
  • 563 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号