记一次goroutine的死锁记录以及解决方法

tomleoken · · 1412 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

**最近开发需要无限循环某个任务,任务里要执行一段代码n次以获取相应的信息,然后合并处理,顺序下来的话时间就是o(n)了,然后go最大的特点不久是强大的并发么,所以想用goroutine来试试水,不料遭遇死锁了,第一次任务循环没问题,但是第二次任务循环就死锁了。** **逻辑是,任务里(无限循环里),开8个协程分别执行8个代码块,然后代码块每执行完一次,slice就+1 。主程再开启一个协程,无线循环检测slice长度,只要长度=8,表示代码块执行完毕,chan释放。** **代码如下** ``` package main import( "log" "time" "sync" ) func main(){ for { //var wg sync.WaitGroup var teststr []string for i := 0; i<8; i++ { //wg.Add(1) go func(t int){ // 隔 n 秒执行一次 //defer wg.Done() log.Println("协程 ",t,"开启") time.Sleep(time.Duration(5)*time.Second) teststr = append(teststr,"haha") log.Println("协程 ",t," 存值完毕") }(i) } log.Println("循环结束") //wg.Wait() channel := make(chan int) go func(){ log.Println("开启判断线程") for { if len(teststr) == 8 { <- channel // 当数组长度与GPU数里相等,即上面的goroutine全部执行完毕 log.Println("通道释放") break } } }() log.Println("通道存值,主线程阻塞") channel <- 1 // 存值,当前线程(main)在此处阻塞 log.Println(teststr) } } ``` **当然最后还是解决了实现了要求,解决方法代码如下** ``` package main import( "log" "time" "sync" ) func main(){ for { var wg sync.WaitGroup var teststr []string for i := 0; i<8; i++ { wg.Add(1) go func(t int){ // 隔 n 秒执行一次 defer wg.Done() log.Println("协程 ",t,"开启") time.Sleep(time.Duration(5)*time.Second) teststr = append(teststr,"haha") log.Println("协程 ",t," 存值完毕") }(i) } log.Println("循环结束") wg.Wait() /* channel := make(chan int) go func(){ log.Println("开启判断线程") for { if len(teststr) == 8 { <- channel // 当数组长度与GPU数里相等,即上面的goroutine全部执行完毕 log.Println("通道释放") break } } }() log.Println("通道存值,主线程阻塞") channel <- 1 // 存值,当前线程(main)在此处阻塞 */ log.Println(teststr) } } ``` **其实代码就是上一篇把sync包的东西去掉注释,然后把channel相关的注释** **虽然解决了,但是还不清楚为何第一段代码为何会死锁,逻辑过了好几遍了,自觉没问题,大家如果发现bug谢谢留言下哈**

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1412 次点击  
加入收藏 微博
4 回复  |  直到 2019-07-31 21:08:40
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传