简体   繁体   English

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

[英]Goroutine does not execute if time.Sleep included

The following code runs perfectly fine: 以下代码运行完全正常:

package main

import (
    "fmt"
)

func my_func(c chan int){
    fmt.Println(<-c)
}

func main(){
    c := make(chan int)
    go my_func(c)

    c<-3
}

playgound_1 playgound_1

However if I change 但是,如果我改变

c<-3

to

time.Sleep(time.Second)
c<-3

playground_2 playground_2

My code does not execute. 我的代码没有执行。

My gut feeling is that somehow main returns before the my_func finishes executing, but it seems like adding a pause should not have any effect. 我的直觉是在my_func完成执行之前以某种方式main返回,但似乎添加暂停应该没有任何效果。 I am totally lost on this simple example, what's going on here? 我完全迷失在这个简单的例子上,这里发生了什么?

When the main function ends, the program ends with it. main函数结束时,程序以它结束。 It does not wait for other goroutines to finish. 它不等待其他goroutines完成。

Quoting from the Go Language Specification: Program Execution : 引用Go语言规范:程序执行

Program execution begins by initializing the main package and then invoking the function main . 程序执行从初始化主包然后调用main函数开始。 When that function invocation returns, the program exits. 当该函数调用返回时,程序退出。 It does not wait for other (non- main ) goroutines to complete. 它不等待其他(非main )goroutines完成。

So simply when your main function succeeds by sending the value on the channel, the program might terminate immediately, before the other goroutine has the chance to print the received value to the console. 因此,当main功能通过在通道上发送值成功时,程序可能会立即终止,然后另一个goroutine有机会将接收到的值打印到控制台。

If you want to make sure the value gets printed to the console, you have to synchronize it with the event of exiting from the main function: 如果要确保将值打印到控制台,则必须将其与退出main函数的事件同步:

Example with a "done" channel (try it on Go Playground ): “完成”频道的示例(在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
}

Since done is also an unbuffered channel, receiving from it at the end of the main function must wait the sending of a value on the done channel, which happens after the value sent on channel c has been received and printed to the console. 由于done也是一个无缓冲的通道,因此在main函数结束时从它接收必须等待在done通道上发送一个值,这在通道c上发送的值被接收并打印到控制台后发生。

Explanation for the seemingly non-deterministic runs: 对看似不确定的运行的解释:

Goroutines may or may not be executed parallel at the same time . 够程可以或可以不被同时并行地执行。 Synchronization ensures that certain events happen before other events. 同步可确保某些事件在其他事件发生之前发生。 That is the only guarantee you get, and the only thing you should rely on. 这是您获得的唯一保证,也是您应该依赖的唯一保证。 2 examples of this Happens Before : 这两个例子发生之前

  • The go statement that starts a new goroutine happens before the goroutine's execution begins. 启动新goroutine的go语句发生在goroutine的执行开始之前。
  • A send on a channel happens before the corresponding receive from that channel completes. 通道上的发送在该通道的相应接收完成之前发生。

For more details read The Go Memory Model . 有关更多详细信息,请参阅Go Memory Model

Back to your example: 回到你的例子:

A receive from an unbuffered channel happens before the send on that channel completes. 来自无缓冲通道的接收在该通道上的发送完成之前发生。

So the only guarantee you get is that the goroutine that runs my_func() will receive the value from channel c sent from main() . 因此,唯一的保证是运行my_func()的goroutine将从main()发送的通道c接收值。 But once the value is received, the main function may continue but since there is no more statements after the send, it simply ends - along with the program. 但是一旦收到值, main函数可能会继续,但由于发送后没有更多的语句,它只是结束 - 与程序一起。 Whether the non- main goroutine will have time or chance to print it with fmt.Println() is not defined . 是否有非main goroutine有时间机会fmt.Println()打印它没有定义

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM