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

如果包含 time.Sleep,Goroutine 不会执行

如果包含 time.Sleep,Goroutine 不会执行

Go
动漫人物 2021-09-13 15:24:48
下面的代码运行得很好:package mainimport (    "fmt")func my_func(c chan int){    fmt.Println(<-c)}func main(){    c := make(chan int)    go my_func(c)    c<-3}但是如果我改变c<-3到time.Sleep(time.Second)c<-3我的代码不执行。我的直觉是main在my_func完成执行之前以某种方式返回,但似乎添加暂停应该没有任何效果。我完全迷失在这个简单的例子中,这里发生了什么?
查看完整描述

1 回答

?
侃侃无极

TA贡献2051条经验 获得超10个赞

main函数结束时,程序也随之结束。它不会等待其他 goroutine 完成。

引用Go 语言规范:程序执行

程序执行首先初始化主包,然后调用函数main。当该函数调用返回时,程序退出。它不会等待其他(非main)goroutine 完成。

因此,当您的main函数通过在通道上发送值而成功时,程序可能会立即终止,然后另一个 goroutine 有机会将接收到的值打印到控制台。

如果要确保将值打印到控制台,则必须将其与退出main函数的事件同步:

带有“完成”频道的示例(在Go Playground上尝试):

func my_func(c, done chan int) {
    fmt.Println(<-c)
    done <- 1}func main() {
    c := make(chan int)
    done := make(chan int)    go my_func(c, done)
    time.Sleep(time.Second)
    c <- 3
    <-done}

由于done也是一个无缓冲通道,因此在main函数结束时从它接收必须等待在done通道上发送一个值,这c是在接收到通道上发送的值并将其打印到控制台之后发生的。

对看似不确定的运行的解释:

够程可能会或可能不会被并行执行在同一时间。同步确保某些事件发生在其他事件之前。这是您获得的唯一保证,也是您唯一应该依赖的东西。之前发生过2 个这样的例子:

  • go启动新 goroutine的语句发生在 goroutine 开始执行之前。

  • 通道上的发送发生在来自该通道的相应接收完成之前。

有关更多详细信息,请阅读Go 内存模型

回到你的例子:

来自无缓冲通道的接收发生在该通道上的发送完成之前。

所以你得到的唯一保证是运行的 goroutinemy_func()将接收cmain(). 但是一旦接收到值,该main函数可能会继续,但由于发送后没有更多语句,它只是结束 - 与程序一起。无论非main够程将有时间机会与打印fmt.Println()没有定义


查看完整回答
反对 回复 2021-09-13
  • 1 回答
  • 0 关注
  • 302 浏览
慕课专栏
更多

添加回答

举报

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