go例程如何完美地交织?

I'm surprised that go routines seem to interleave perfectly... After seeing this, I am starting to believe there's some missing information about the internals that I haven't learned about yet. Example:

$ 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
    }
}

However long you set the timeout in the player function (or remove it all together) you always get #ping == #ping +/- 1.

By default GOMAXPROCS is set to 1 and as a result you see this behaviour. If you increase GOMAXPROCS it will no longer be deterministic.

See this answer for an example

EDIT @DaveC disagrees however a simple test shows otherwise. The channels are synchonised yes, however the order of the goroutines executing is not. These are different concepts. Type in the above code, set GOMAXPROCS > 1 and run ...

➜  tmp  export GOMAXPROCS=2
➜  tmp  go run balls.go
ping 1
pong 2
➜  tmp  go run balls.go
pong 1
ping 2
➜  tmp

As you can see above the goroutines order of execution is not deterministic

You're using a un-buffered channel and your two goroutines synchronize with it. With an un-buffered channel the channel write (table <- ball) can only complete once someone somewhere has done a read (<-table) so a single goroutine can never read the value it's writing. That's the whole point of this example.

According to this blog:

Goroutines would interleave perfectly for any number of players:

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