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

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

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

Go
ibeautiful 2021-05-04 18:50:06
package mainimport "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
查看完整描述

2 回答

?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

从Goexit的文档中:


Goexit终止调用它的goroutine。没有其他goroutine受到影响。Goexit在终止goroutine之前运行所有延迟的调用。


您正在退出主例程。别。当您执行此操作时,在您启动的最后一个启动go check(i)完成之后,没有任何例程在运行,因此出现“死锁”。只需删除此行:


defer runtime.Goexit()

如果您要在main中等待一组goroutine完成,则可以使用sync.WaitGroup:


package main


import (

    "fmt"

    "sync"

    "time"

)


func check(id int, wg *sync.WaitGroup) {

    fmt.Println("Checked", id)

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

    fmt.Println("Woke up", id)

    wg.Done()

}


func main() {

    var wg sync.WaitGroup

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

        wg.Add(1)

        fmt.Println("Called with", i)

        go check(i, &wg)

    }

    wg.Wait()

    fmt.Println("Done for")

}

编辑 :


如果您在golang的操场上进行测试,则任何人time.After都将陷入僵局,因为时间在操场上被冻结,Goexit可能退出标准程序中甚至不存在的例程。


查看完整回答
反对 回复 2021-05-17
?
斯蒂芬大帝

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

您的所有goroutine都在等待某人消耗他们发送的值<-time.After。您只需删除<-或使main消耗您启动的所有goroutine的值即可。


编辑


这对我有用


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")

}

女巫与某人之前提出的解决方案相同,所以我将在没有等待组的情况下提出解决方案


package main


import "fmt"

import "time"



func check(id int, c chan bool) {

    fmt.Println("Checked", id)

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

    fmt.Println("Woke up", id)

    c <- true

}


func main() {

    c := make(chan bool)


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

        fmt.Println("Called with", i)

        go check(i, c)

    }

    var n uint

    for n<10 {

        <- c

        n++

    }

    fmt.Println("Done for")

}


查看完整回答
反对 回复 2021-05-17
  • 2 回答
  • 0 关注
  • 172 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信