如何完成例程交错?

Jam*_*mes 1 go goroutine

令我感到惊讶的是,惯例似乎完全交错......看到这个之后,我开始相信有一些关于内部的缺失信息,我还没有学到.例:

$ 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
    }
}
Run Code Online (Sandbox Code Playgroud)

无论你在播放器功能中设置超时(或者将它们全部一起移除),你总是得到#ping == #ping +/- 1.

Dav*_*e C 6

您正在使用未缓冲的通道,并且您的两个goroutine与它同步.使用非缓冲通道,通道write(table <- ball)只能在某个地方某人完成read(<-table)后才能完成,因此单个goroutine永远无法读取它所写的值.这就是这个例子的重点.

  • 这里已多次提到无缓冲信道的行为.这是不可能的,因为`table < - ball`直到*之后才返回*`ball:= < - table`在另一个例程中返回.当第一个goroutine通过for循环返回并尝试再次读取时,它必须等待另一个不同的通道发送. (3认同)