猿问

为什么此Go代码陷入僵局?

package main


import "fmt"

import "runtime"

import "time"



func check(id int) {

    fmt.Println("Checked", id)

    <-time.After(time.Duration(id)*time.Millisecond)

    fmt.Println("Woke up", id)

}


func main() {

    defer runtime.Goexit()


    for i := 0; i <= 10; i++ {

        fmt.Println("Called with", i)

        go check(i)

    }


    fmt.Println("Done for")

}

我是Go的新手,所以任何指针都很棒。我将如何调试这样的事情?


您可以运行代码段http://play.golang.org/p/SCr8TZXQUE


ibeautiful
浏览 173回答 2
2回答

米琪卡哇伊

从Goexit的文档中:Goexit终止调用它的goroutine。没有其他goroutine受到影响。Goexit在终止goroutine之前运行所有延迟的调用。您正在退出主例程。别。当您执行此操作时,在您启动的最后一个启动go check(i)完成之后,没有任何例程在运行,因此出现“死锁”。只需删除此行:defer runtime.Goexit()如果您要在main中等待一组goroutine完成,则可以使用sync.WaitGroup:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "sync"&nbsp; &nbsp; "time")func check(id int, wg *sync.WaitGroup) {&nbsp; &nbsp; fmt.Println("Checked", id)&nbsp; &nbsp; <-time.After(time.Duration(id)*time.Millisecond)&nbsp; &nbsp; fmt.Println("Woke up", id)&nbsp; &nbsp; wg.Done()}func main() {&nbsp; &nbsp; var wg sync.WaitGroup&nbsp; &nbsp; for i := 0; i <= 10; i++ {&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Called with", i)&nbsp; &nbsp; &nbsp; &nbsp; go check(i, &wg)&nbsp; &nbsp; }&nbsp; &nbsp; wg.Wait()&nbsp; &nbsp; fmt.Println("Done for")}编辑 :如果您在golang的操场上进行测试,则任何人time.After都将陷入僵局,因为时间在操场上被冻结,Goexit可能退出标准程序中甚至不存在的例程。

斯蒂芬大帝

您的所有goroutine都在等待某人消耗他们发送的值<-time.After。您只需删除<-或使main消耗您启动的所有goroutine的值即可。编辑这对我有用package mainimport "fmt"//import "runtime"import "time"func check(id int) {&nbsp; &nbsp; fmt.Println("Checked", id)&nbsp; &nbsp; <-time.After(time.Duration(id)*time.Millisecond)&nbsp; &nbsp; fmt.Println("Woke up", id)}func main() {&nbsp; &nbsp; //defer runtime.Goexit()&nbsp; &nbsp; for i := 0; i <= 10; i++ {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Called with", i)&nbsp; &nbsp; &nbsp; &nbsp; go check(i)&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println("Done for")}女巫与某人之前提出的解决方案相同,所以我将在没有等待组的情况下提出解决方案package mainimport "fmt"import "time"func check(id int, c chan bool) {&nbsp; &nbsp; fmt.Println("Checked", id)&nbsp; &nbsp; time.After(time.Duration(id)*time.Millisecond)&nbsp; &nbsp; fmt.Println("Woke up", id)&nbsp; &nbsp; c <- true}func main() {&nbsp; &nbsp; c := make(chan bool)&nbsp; &nbsp; for i := 0; i <= 10; i++ {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Called with", i)&nbsp; &nbsp; &nbsp; &nbsp; go check(i, c)&nbsp; &nbsp; }&nbsp; &nbsp; var n uint&nbsp; &nbsp; for n<10 {&nbsp; &nbsp; &nbsp; &nbsp; <- c&nbsp; &nbsp; &nbsp; &nbsp; n++&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println("Done for")}
随时随地看视频慕课网APP

相关分类

Go
我要回答