9

我是 Go 新手,在理解并发和通道时遇到了问题。

package main

import "fmt"

func display(msg string, c chan bool){
    fmt.Println("display first message:", msg)
    c <- true
}

func sum(c chan bool){
    sum := 0
    for i:=0; i < 10000000000; i++ {
        sum++
    }
    fmt.Println(sum)
    c <- true
}

func main(){
    c := make(chan bool)

    go display("hello", c)
    go sum(c)
    <-c
}

程序的输出是:

display first message: hello
10000000000 

但我认为应该只有一行:

display first message: hello

所以在 main 函数中,<-c 正在阻塞它并等待另外两个 go rountines 向通道发送数据。一旦 main 函数从 c 接收到数据,它应该继续并退出。

display 和 sum 同时运行并且 sum 需要更长的时间,因此 display 应该将 true 发送到 c 并且程序应该在 sum 完成之前退出......

我不确定我是否清楚地理解它。有人可以帮我解决这个问题吗?谢谢!

4

1 回答 1

4

程序的确切输出没有定义,取决于调度程序。调度器可以在所有当前未被阻塞的 goroutine 之间自由选择。它尝试通过在非常短的时间间隔内切换当前的 goroutine 来同时运行这些 goroutine,以便用户感觉到一切都是同时发生的。除此之外,它还可以在不同的 CPU 上并行执行多个 goroutine(如果你碰巧有一个多核系统并增加runtime.GOMAXPROCS)。可能导致您输出的一种情况是:

  1. main创建两个 goroutine
  2. 调度程序选择立即切换到新的 goroutine 之一并选择display
  3. display打印出消息并被通道发送(c <- true)阻止,因为还没有接收者。
  4. 调度程序选择sum下一个运行
  5. 计算总和并打印在屏幕上
  6. 调度程序选择不恢复sumgoroutine(它已经使用了相当长的时间)并继续display
  7. display将值发送到通道
  8. 调度程序选择下一个运行 main
  9. main 退出,所有 goroutine 都被销毁

但这只是一种可能的执行顺序。还有很多其他的,其中一些会导致不同的输出。如果您只想打印第一个结果并随后退出程序,您可能应该使用 aresult chan string并将您的main函数更改为 print fmt.Println(<-result)

于 2013-08-22T22:53:52.943 回答