drymoeuka282427675 2016-05-11 08:25
浏览 22
已采纳

为什么我的go程序陷入僵局?

I am very new to golang programming and I have the following program which produces deadlock, I don't understand why ?

Another thing is if I close the channel in doAdd method then I go into an infinite loop, that's also bit strange for me.

Here is the program.

var wg sync.WaitGroup

func main() {

    ch1 := make(chan string)
    ch2 := make(chan string)
    ch3 := make(chan string)
    chClose := make(chan bool)
    wg.Add(3)
    go doAdd(ch1, "ch1")
    go doAdd(ch2, "ch2")
    go doAdd(ch3, "ch3")

    go waitForClose(chClose)

    for {
        select {
        case x := <-ch1:
            fmt.Println("Got from ch1 ", x)
        case y := <-ch2:
            fmt.Println("Got from ch2 ", y)
        case z := <-ch3:
            fmt.Println("Got from ch3 ", z)
        case <-chClose:
            fmt.Println("CLOSED")
            break
        }
    }
}

func waitForClose(chClose chan bool) {
    wg.Wait()
    chClose <- true
}

func doAdd(ch chan string, name string) {
    for i := 0; i < 10; i++ {
        ch <- strconv.Itoa(i)
    }
    wg.Done()
}

and the output is:

Got from ch1  0
Got from ch1  1
Got from ch1  2
Got from ch1  3
Got from ch1  4
Got from ch1  5
Got from ch1  6
Got from ch1  7
Got from ch1  8
Got from ch1  9
Got from ch2  0
Got from ch2  1
Got from ch2  2
Got from ch2  3
Got from ch2  4
Got from ch2  5
Got from ch2  6
Got from ch2  7
Got from ch2  8
Got from ch2  9
Got from ch3  0
Got from ch3  1
Got from ch3  2
Got from ch3  3
Got from ch3  4
Got from ch3  5
Got from ch3  6
Got from ch3  7
Got from ch3  8
Got from ch3  9
CLOSED
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [select]:
main.main()
        c:/PraveenData/demo/go-work/main.go:29 +0x915
exit status 2
  • 写回答

2条回答 默认 最新

  • duanchen1937 2016-05-11 08:37
    关注

    The reason you get a deadlock is that the break inside your select only breaks out of the select, leaving the for loop free to re-enter the select, where none of the channels are ready to read from.

    You could rescue this by doing something like:

    done := false
    
    for !done {
            select {
                   ...
            case <-chClose:
                    done = true
                    fmt.Println("CLOSED")
            }
    }
    

    This trivially allows the for loop to terminate.

    The other would be to use a label:

    OuterLoop:
            for {
                    select {
                    ...
                    case <-chClose:
                            fmt.Println("CLOSED")
                            break OuterLoop
                    }
            }
    

    I, personally, have a slight preference for the first version in this case, but that is merely a matter of taste.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!