请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于channel报错的问题请教

图片描述

你好,老师,请帮忙看下截图代码,任务tast打印完后,会报错 - deadlock!,怎么解决这个问题呢,使其能优雅退出或者阻塞等待,请老师指点

注:上述代码是从课程中 简单版并发爬虫的实例中提取出来的。课程中并发爬虫执行完进入循环等待中。而我上述我的代码则会报deadlock错

正在回答 回答被采纳积分+3

2回答

兰陵笑_生 2019-06-24 23:36:29

woker()方法中从<-in那个channel取出数据加了延迟,而往channel中传入数据没加延迟,导致处理来不及。而引发死锁。


1 回复 有任何疑惑可以回复我~
  • 提问者 liyongwei #1
    我觉得不是sleep延迟的问题,可以把这行注掉,还是会报错的
    回复 有任何疑惑可以回复我~ 2019-06-28 11:24:51
  • 兰陵笑_生 回复 提问者 liyongwei #2
    看了下当for循环读完channel的值之后会继续尝试读取下一个,而由于channel为空又没关闭,会一直阻塞形成死锁。读完值后把channel关闭了就可以了
    回复 有任何疑惑可以回复我~ 2019-06-28 16:39:30
FrankieLee 2019-08-11 15:30:30
/**
死锁发生的原因是因为主进程在等待out这个通道返回数据,如果这个时候out被关闭的话,程序就会正常结束,但是out这个通道是在worker里面发送数据的,worker也不知道什么时候关闭out,因为worker最后也会因为in里读不到数据而阻塞。从修复问题的层面上来将,这个case应该在main里向in发送数据,发送完毕之后关闭通道in,这样worker就可以在读取完in的数据之后关闭out通道,避免main在读取时发生阻塞,代码如下
**/
package main

import (
  "fmt"
  "strconv"
  "time"
)

func main() {
  in := make (chan int)
  out := make(chan string, 10)
  tasks := []int{1, 2, 3 , 4, 5, 6, 7, 8, 9, 10}
  go worker(in, out)
  for _, v := range tasks {
     in <- v
  }
  close(in)
  receiver(out)
  time.Sleep(time.Second * 1)
}

func receiver(out chan string) {
  for ret := range out {
     fmt.Println(ret)
  }
}

func worker(in chan int, out chan string) {
  for res := range in{
     ret := "返回结果:"
     ret += strconv.Itoa(res)
     out <- ret
     time.Sleep(time.Millisecond * 50)
  }
  close(out)
}
0 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信