执行顺序在go协程中的顺序

huangapple go评论83阅读模式
英文:

Order of execution inside go routines

问题

我最近开始学习Go语言,对于这个程序的执行顺序感到非常困惑。希望我在这里没有问一些非常琐碎的问题。

这基本上是Go语言之旅中的第69个例子,我插入了一些Println语句;Playground链接:http://play.golang.org/p/PXDlD3EA2f

func fibonacci(c, quit chan int) {
    x, y := 0, 1

    fmt.Println("Inside the fibonacci")

    for {
        select {
        case c <- x:
            fmt.Println("Inside the for, first case, before reassigning ", x, y)
            x, y = y, x+y
            fmt.Println("Inside the for, first case, after reassigning ", x, y)
        case <-quit:
            fmt.Println("quit")
            return
        }
    }
}

func main() {
    fmt.Println("Begin of Main")
    c := make(chan int)
    quit := make(chan int)
    fmt.Println("Before going to the func")
    go func() {
        fmt.Println("Inside go routine")
        fmt.Println("Inside go routine... again")
        for i := 0; i < 10; i++ {
            fmt.Println("Inside go routine and the for, before printing the channel")
            fmt.Println(<-c)
        }
        quit <- 0
    }()
    fmt.Println("Before calling to fibonacci")
    fibonacci(c, quit)
    fmt.Println("Closing")
}

在我得到的非常冗长的输出中(见下面附图),有几件事我不明白:

  • 为什么"Inside the fibonacci"这一行在go例程中的行之前?这是因为在go命令之后,编译器同时在func和fibonacci中读取吗?

  • fibonacci和func是如何交互的?func没有改变通道c,那为什么fibonacci会有反应?是谁改变了c?

  • 为什么在fibonacci中每次都有5个打印输出?老实说,我只期望有2个。

函数的输出结果:

执行顺序在go协程中的顺序

英文:

I recently started with go and I am really confused about the order of execution of this program. I hope I am not asking really trivial questions here.

This is basically #69 in the golang tour, with some Println I have inserted; Link to playground: http://play.golang.org/p/PXDlD3EA2f

func fibonacci(c, quit chan int) {
	x, y := 0, 1

	fmt.Println(&quot;Inside the fibonacci&quot;)

	for {
		select {
		case c &lt;- x:
			fmt.Println(&quot;Inside the for, first case, before reassigning &quot;, x, y)
			x, y = y, x+y
			fmt.Println(&quot;Inside the for, first case, after reassigning &quot;, x, y)
		case &lt;-quit:
			fmt.Println(&quot;quit&quot;)
			return
		}
	}
}

func main() {
	fmt.Println(&quot;Begin of Main&quot;)
	c := make(chan int)
	quit := make(chan int)
	fmt.Println(&quot;Before gonig to the func&quot;)
	go func() {
		fmt.Println(&quot;Inside go routine&quot;)
		fmt.Println(&quot;Inside go routine... again&quot;)
		for i := 0; i &lt; 10; i++ {
			fmt.Println(&quot;Inside go routine and the for, before printing the channel&quot;)
			fmt.Println(&lt;-c)
		}
		quit &lt;- 0
	}()
	fmt.Println(&quot;Before calling to fibonacci&quot;)
	fibonacci(c, quit)
	fmt.Println(&quot;Closing&quot;)
}

In the very verbose output I obtain (see attached image below), there are a couple of things I do not understand:

  • why is the "Inside the fibonacci" line before the ones in the go routine? Is this because after the go command, the compiler is just reading at the same time inside func and fibonacci?

  • how do fibonacci and func interact? func is not changing the channel c, so why is fibonacci reacting? Who's changing c?

  • why inside fibonacci there are 5 prints together every time? Honesty I was expecting only 2.

Output of the function:

执行顺序在go协程中的顺序

答案1

得分: 6

让我们一步一步来解释:

* 为什么"go routine"中的"Inside the fibonacci"行在函数中的行之前?这是因为在使用"go"命令之后,编译器同时在函数和fibonacci中读取吗?

因为你的"go routine"实际上是在调用fibonacci之后开始的,调度器需要一点时间来启动。例如,如果你启动一个调用fmt.Println的"go routine",并且在"main"中没有等待的操作,程序将在执行之前退出。

* fibonacci和func是如何交互的?func没有改变通道c,为什么fibonacci会有反应?谁改变了c?

fibonacci将数字推送到通道中,注意这部分代码:

select {
        case c <- x: //这是将x发送到通道中

* 为什么每次在fibonacci中有5个打印输出?我本来期望只有2个。

这再次取决于调度器以及fmt.Print*不会锁定stdout,输出的顺序可以是任意的,因为它是两个不同的线程打印的内容。

英文:

Let's take it step by step:

* why is the "Inside the fibonacci" line before the ones in the go routine? Is this because after the go command, the compiler is just reading at the same time inside func and fibonacci?

Because your go routine actually starts after you call fibonacci, the scheduler takes a little bit of time to start, for example if you start a goroutine that calls fmt.Println and do nothing to wait in main, the program will exit before it gets executed.

* how do fibonacci and func interact? func is not changing the channel c, so why is fibonacci reacting? Who's changing c?

fibonacci is pushing numbers into the channel, notice this part:

select {
        case c &lt;- x: //this is sending x to the channel

* why inside fibonacci there are 5 prints together every time? Honesty I was expecting only 2.

That again depends on the scheduler and the fact that fmt.Print* doesn't lock stdout, the output can happen in any order since it's 2 different threads printing stuff.

答案2

得分: 1

这个演示非常有用,可以帮助你理解通道的工作原理:Google I/O 2012 - Go Concurrency Patterns。在这个视频中,你可以找到你问题的答案。

英文:

Not really an answer, but i found this presentation very handy to understand how channels work: Google I/O 2012 - Go Concurrency Patterns
In here you find answers for your questions.

huangapple
  • 本文由 发表于 2014年8月21日 11:51:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/25417961.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定