为什么这段代码会失速?

时间:2018-02-23 04:42:52

标签: go concurrency

主要的例行程序将球放在一个通道上。玩家goroutine获得球,操纵它,然后将球放回通道并循环。此时它停滞不前。

为什么玩家会停转?不应该能够拿起"球"从自己?对不起,如果这是正确地盯着我,但我对golang并发的理解让我相信玩家常规应该能够自己打乒乓球。

type Ball struct{ hits int }


func main() {
    table := make(chan *Ball)
    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(100 * time.Millisecond)
        table <- ball
    }
}

1 个答案:

答案 0 :(得分:4)

它没有停滞。
它只是退出。

这是因为当发回球时,球员必须等待main例程才能拿起球。
一旦主程序接到球......就会退出 这会中断所有当前的goroutine,这意味着播放器完成的循环已停止。

actual example就在这里......它有两个玩家。

只需添加:

go player("ping", table)

而你will see (playground)

ping 1
pong 2
ping 3
pong 4
ping 5
pong 6
ping 7
pong 8
ping 9
pong 10
ping 11
pong 12

OP添加in the comments

  

我的意思是,为什么它不会在player中循环多次?   如果你将睡眠时间增加到10,那就更明显了

这是playground example with main waiting 10 seconds

player不会循环,因为table无缓冲的频道:一旦玩家将球发回,玩家阻止,直到任何人移除桌子上的球。
并且没有人可以删除所说Ballmain正在睡10秒,然后将其删除并立即退出,阻止玩家再循环一次(因为全部程序已停止)

请参阅“do Golang channels maintain order”,以查看无缓冲与缓冲频道的说明。

桌子休息10秒,带有缓冲频道(容量为1),here is what you would see (playground)(播放器休眠1秒):

pong 1
pong 2
pong 3
pong 4
pong 5
pong 6
pong 7
pong 8
pong 9
pong 10
pong 11
time's up

即:player 1Ball中选择table,并将其发回表格。它不会阻塞,因为缓冲的通道不会过载。