go routines 怎么可能完美交错呢?
How is it possible that go routines interleave perfectly?
令我惊讶的是,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。
您使用的是无缓冲通道,并且您的两个 goroutine 与其同步。对于无缓冲通道,通道写入 (table <- ball
) 只能在某处有人完成读取 (<-table
) 后才能完成,因此单个 goroutine 永远无法读取它正在写入的值。这就是这个例子的重点。
默认情况下 GOMAXPROCS 设置为 1,因此您会看到此行为。如果你增加 GOMAXPROCS 它将不再是确定性的。
请参阅 示例
编辑 @DaveC 不同意,但是一个简单的测试表明情况并非如此。通道是同步的,但是 goroutines 的执行顺序不是。这些是不同的概念。输入上面的代码,设置 GOMAXPROCS > 1 and 运行 ...
➜ tmp export GOMAXPROCS=2
➜ tmp go run balls.go
ping 1
pong 2
➜ tmp go run balls.go
pong 1
ping 2
➜ tmp
正如您在上面看到的,goroutines 的执行顺序是不确定的
据此blog:
Goroutines 可以为任意数量的玩家完美交错:
The answer is because Go runtime holds waiting FIFO queue for receivers (goroutines ready to receive on the particular channel), and
in our case every player gets ready just after he passed the ball on
the table
令我惊讶的是,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。
您使用的是无缓冲通道,并且您的两个 goroutine 与其同步。对于无缓冲通道,通道写入 (table <- ball
) 只能在某处有人完成读取 (<-table
) 后才能完成,因此单个 goroutine 永远无法读取它正在写入的值。这就是这个例子的重点。
默认情况下 GOMAXPROCS 设置为 1,因此您会看到此行为。如果你增加 GOMAXPROCS 它将不再是确定性的。
请参阅
编辑 @DaveC 不同意,但是一个简单的测试表明情况并非如此。通道是同步的,但是 goroutines 的执行顺序不是。这些是不同的概念。输入上面的代码,设置 GOMAXPROCS > 1 and 运行 ...
➜ tmp export GOMAXPROCS=2
➜ tmp go run balls.go
ping 1
pong 2
➜ tmp go run balls.go
pong 1
ping 2
➜ tmp
正如您在上面看到的,goroutines 的执行顺序是不确定的
据此blog:
Goroutines 可以为任意数量的玩家完美交错:
The answer is because Go runtime holds waiting FIFO queue for receivers (goroutines ready to receive on the particular channel), and in our case every player gets ready just after he passed the ball on the table