首页 > 解决方案 > 为什么调用 goroutine 的顺序和方式很重要?

问题描述

我正在尝试理解 goroutines。在以下示例中,为什么 1)--4) 的行为不同?见https://play.golang.org/p/_XXZe47W53v

package main
import (
  "fmt"
  "time"
)

func send(x int, ch chan int) {ch<-x}
func read(ch chan int) {fmt.Println(<-ch)}

func main() {
    ch := make(chan int)

    go read(ch)              // 1) works
    go send(1,ch)            // -> 1

    // go fmt.Println(<-ch)  // 2) fatal error: all goroutines are asleep - deadlock!
    // go send(1,ch)         // isn't this the same as the above ?

    // go send(1,ch)         // 3) works
    // go fmt.Println(<-ch)  // -> 1

    // go fmt.Println(<-ch)  // 4) fatal error: all goroutines are asleep - deadlock!
    // go send(1,ch)         // why does the order of the go routine calls matter?

    time.Sleep(100*time.Millisecond)
}

标签: gogoroutine

解决方案


您看到错误是因为读取不是发生在 goroutine 内部,而是发生在主线程中。

该行:

go fmt.Println(<-ch)

正在评估主线程中的参数,一旦成功,它将Println使用已解析的参数在 goroutine 中运行。由于ch在这种状态下代码永远无法写入,它会死锁。

您可以通过将其更改为:

go func() { fmt.Println(<-ch) }()

ch然后它会围绕send().


推荐阅读