go 例程怎么可能完美地交错?

我很惊讶 go 例程似乎完美地交错......看到这个之后,我开始相信有一些关于内部结构的缺失信息,我还没有了解。例子:


$ go run x.go > output

$ grep ping output | wc -l

404778

$ grep pong output | wc -l

404777

$ cat x.go 

package main

import (

    "fmt"

    "time"

)


type Ball struct{ hits int }


func main() {

    table := make(chan *Ball)

    go player("ping", table)

    go player("pong", table)


    table <- new(Ball) // game on; toss the ball

    time.Sleep(1 * time.Second)

    <-table // game over; grab the ball

}


func player(name string, table chan *Ball) {

    for {

        ball := <-table

        ball.hits++

        fmt.Println(name, ball.hits)

        //time.Sleep(1 * time.Millisecond)

        table <- ball

    }

}

无论您在播放器功能中设置超时时间(或将其全部删除),您总是会得到 #ping == #ping +/- 1。


米琪卡哇伊
浏览 197回答 3
3回答

森栏

您正在使用无缓冲通道,并且您的两个 goroutine 与其同步。使用非缓冲通道,通道写入 (&nbsp;table <- ball) 只能在某个地方有人完成读取 (&nbsp;<-table) 后才能完成,因此单个 goroutine 永远无法读取它正在写入的值。这就是这个例子的全部意义。

千万里不及你

Goroutines 可以为任意数量的玩家完美地交错:答案是因为 Go 运行时为接收者持有等待FIFO 队列(goroutines 准备在特定通道上接收),在我们的例子中,每个玩家在他把球传到桌子上后就准备好了

30秒到达战场

默认情况下GOMAXPROCS设置为 1,因此您会看到此行为。如果您增加 GOMAXPROCS,它将不再具有确定性。请参阅此答案以获取示例编辑@DaveC 不同意,但一个简单的测试表明并非如此。通道是同步的,但是 goroutine 执行的顺序不是。这些是不同的概念。输入上面的代码,设置 GOMAXPROCS > 1 并运行...➜&nbsp; tmp&nbsp; export GOMAXPROCS=2➜&nbsp; tmp&nbsp; go run balls.goping 1pong 2➜&nbsp; tmp&nbsp; go run balls.gopong 1ping 2➜&nbsp; tmp正如你在上面看到的,goroutines 的执行顺序不是确定性的
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go