为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
米琪卡哇伊 2021-09-21 17:23:57
我很惊讶 go 例程似乎完美地交错......看到这个之后,我开始相信有一些关于内部结构的缺失信息,我还没有了解。例子:$ go run x.go > output$ grep ping output | wc -l404778$ grep pong output | wc -l404777$ cat x.go package mainimport (    "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。
查看完整描述

3 回答

?
森栏

TA贡献1810条经验 获得超5个赞

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


查看完整回答
反对 回复 2021-09-21
?
千万里不及你

TA贡献1784条经验 获得超9个赞

Goroutines 可以为任意数量的玩家完美地交错:

答案是因为 Go 运行时为接收者持有等待FIFO 队列(goroutines 准备在特定通道上接收),在我们的例子中,每个玩家在他把球传到桌子上后就准备好了


查看完整回答
反对 回复 2021-09-21
?
30秒到达战场

TA贡献1828条经验 获得超6个赞

默认情况下GOMAXPROCS设置为 1,因此您会看到此行为。如果您增加 GOMAXPROCS,它将不再具有确定性。


请参阅此答案以获取示例


编辑@DaveC 不同意,但一个简单的测试表明并非如此。通道是同步的,但是 goroutine 执行的顺序不是。这些是不同的概念。输入上面的代码,设置 GOMAXPROCS > 1 并运行...


➜  tmp  export GOMAXPROCS=2

➜  tmp  go run balls.go

ping 1

pong 2

➜  tmp  go run balls.go

pong 1

ping 2

➜  tmp

正如你在上面看到的,goroutines 的执行顺序不是确定性的


查看完整回答
反对 回复 2021-09-21
  • 3 回答
  • 0 关注
  • 196 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信