go例程如何能够完美地交织?

go例程如何能够完美地交织?,go,goroutine,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() {

我很惊讶围棋套路似乎完美地交织在一起。。。在看到这些之后,我开始相信我还没有了解到一些关于内部的信息。例如:

$ 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
    }
}
$go运行x.go>输出
$grep ping输出| wc-l
404778
$grep pong输出| wc-l
404777
$cat x.go
包干管
进口(
“fmt”
“时间”
)
键入Ball结构{hits int}
func main(){
表:=制造(成龙*球)
围棋玩家(“平”,桌子)
围棋玩家(“乒乓球”,桌上)

table您正在使用一个未缓冲的通道,并且两个goroutine与之同步。对于未缓冲的通道,通道写入(
table默认设置为1,因此您会看到这种行为。如果增加GOMAXPROCS,它将不再是确定性的

请参阅以获取示例

EDIT@DaveC不同意,但一个简单的测试表明并非如此。通道是同步的是,但goroutines的执行顺序不是。这些是不同的概念。键入上述代码,设置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的执行顺序是不确定的,根据这一点:

Goroutines可以完美地交错,适合任何数量的玩家:

答案是因为Go运行时保持等待(goroutines准备在特定通道上接收),并且 在我们的例子中,每个球员在传球后都会做好准备 桌子


换句话说,问题所指的“缺少的信息”是,无缓冲通道发送是同步的:发送goroutine进入睡眠状态,直到另一个接收到该值。如果您想了解这是如何发生的,请查找goroutine调度程序(类似于控制操作系统中线程的调度程序)的信息换句话说,你已经发现了使用通信顺序过程(CSP)的一个伟大特性,它是Go模型的基础:你所看到的是你从“这发生”到“那发生”所得到的。这在涉及外部i/o时变得特别有用-您不必编写回调链。只需阻塞即可。在代码中,哪里说在ping完成后不能立即进行ping调用?不可能吗?这里已经多次提到了无缓冲通道的行为。这是不可能的,因为
table Inco请更正,重新阅读代码。无论允许多少线程,未缓冲的通道都是同步的。这是我一直在寻找的答案……目前我不清楚它是否适用于这个特定的代码问题。我希望ping可以在ping之后立即调用,从而跳过pong,但也许我是新手golang,因此可能遗漏了语言中一些未记录的细微差别。@DaveC使用示例输出进行编辑。我理解,由于频道同步,频道将始终从乒乓球切换到乒乓球(或反之亦然),而从不从乒乓球切换到乒乓球或乒乓球。@LenW这与goroutine开始的点(乒乓球或乒乓球)无关。问题是,为什么一个ping总是跟在一个ping之后,而不是另一个ping。正确的答案与GOMAXPROCS无关。正如@Dave C正确写道的那样,
我同意你的观察结果,即输出是不确定的(因为它可能以ping或pong开始),但问题是关于乒乓球和乒乓球的“完美交错”。所以我认为这个答案并没有以一种有用的方式回答这个问题,即使它说的在技术上是正确的。你应该接受@Dave C的答案。