首页 > 解决方案 > 为什么 goroutine 中的无缓冲通道得到这个顺序

问题描述

我正在用 goroutine 和通道编写一些 golang 并发代码,这是我的代码:

package main

import "fmt"

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

    go func() {
        fmt.Println("Adding num to channel")
        in <- 1
        fmt.Println("Done")
    }()
    val := <- in
    fmt.Println(val)
}

我做了一个无缓冲的通道,在我看来,里面的通道必须等到外面的通道读取它,输出可能是这样的:

Adding num to channel
1
Done

但实际上,输出是:

Adding num to channel
Done
1

我很困惑,为什么内部无缓冲通道无需等待读取就运行

标签: gochannelgoroutine

解决方案


您对输出的解释不正确。goroutine 确实写入了通道,此时主 goroutine 确实读取了,但是“完成”的 printf 在值的 printf 之前执行。

同步操作在 goroutine 之间建立了“之前发生过”的关系。当 goroutine 写入通道时,唯一能保证在通道写入之前发生的事情是 goroutine 中的第一个 println。一旦通道写入和相应的读取完成,剩下的 goroutine 和主 goroutine 可以以任意顺序执行。

在您的情况下,goroutine 在主 goroutine 之前执行。


推荐阅读