Go 中的简单通道的竞争条件?

我是 Go 的新手,并且对在带有 Go 1.2 版的 Linux 上运行的一小块代码似乎有点罕见的竞争条件感到困惑。


基本上,我为 an 创建一个通道int,启动一个 go 例程从该通道读取,然后将单个 int 写入该通道。


package main


import "fmt"


func main() {

    channel := make(chan int)


    go func() {

        number := <- channel

        fmt.Printf("GOT IT: %d\n", number)

    }()


    fmt.Println("[+] putting num on channel")

    channel <- 42

    fmt.Println("[-] putting num on channel")

}

大约 90% 的时间输出符合预期:


$ go run test.go 

[+] putting num on channel

GOT IT: 42

[-] putting num on channel

然而,大约有 10% 的时间,go 例程不会从通道中读取数字并且不打印任何内容:


$ go run test.go 

[+] putting num on channel

[-] putting num on channel

我很困惑,因为这段代码与https://gobyexample.com/channels上的示例非常相似,(我没有这个问题),除了我在 go 例程中从通道读取而不是编写到频道。


我是否对渠道的工作方式有根本的误解,或者这里还有其他东西在起作用吗?


动漫人物
浏览 189回答 3
3回答

桃花长相依

您似乎希望接收 goroutine 在第二个fmt.Println执行之前运行完成。不能保证情况如此。如果程序终止,goroutine 不能保证到达其函数的末尾。当你看到没有显示“GOT IT”消息的输出时,通道传递了它的消息,但main函数在 goroutine 之前完成。程序终止,goroutine 永远没有机会调用fmt.Printf在您引用的示例中,该main函数以以下内容结尾:go func() { messages <- "ping" }()msg := <-messagesfmt.Println(msg)由于main函数在收到消息之前会阻塞,因此在这个例子中 goroutine 总是运行到完成。在您的代码中,您的 goroutine 在从通道接收后执行一个步骤,并且未定义 goroutine 或 main 函数是否会在接收后执行下一行。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go