duanguo7021 2018-02-23 04:42
浏览 27
已采纳

为什么此代码停顿?

The main go routine places a ball on a channel. The player goroutine gets the ball, manipulates it, then places the ball back on the channel and loops. At this point it stalls.

Why does the player goroutine stall? Shouldn't it be able to pick up the "ball" from itself? Sorry if this is staring me right in the face, but my understanding of golang concurrency leads me to believe the player go routine should be able to play ping pong all by itself.

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条回答 默认 最新

  • duanlie3187 2018-02-23 05:47
    关注

    It does not stall.
    It just exits.

    That is because the player, when sending back the Ball, will have to wait for the main routine to pick it up.
    And once the main routine has received the ball... it exits.
    That interrupts all current goroutine, meaning the loop done by player is stopped.

    The actual example is here... and it has two players.

    Just add:

    go player("ping", table)
    

    And you 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
    

    The OP adds in the comments:

    I meant, why doesn't it loop more than once in player?
    If you increase the sleep time to 10 it becomes more evident

    Here is a playground example with main waiting 10 seconds.

    player won't loop because table is an unbuffered channel: once player send the Ball back, player blocks until anyone removes that Ball from table.
    And there is nobody to remove said Ball: main is sleeping 10 seconds, then removes it and exits immediately, preventing player to loop some more (because the all program has stopped)

    See "do Golang channels maintain order", in order to see an illustration of unbuffered vs. buffered channels.

    With table sleeping 10 seconds, but with a buffered channel (of capacity 1), here is what you would see (playground) (the player sleeps 1 second):

    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
    

    That is: the player 1 pick itself the Ball from the table, and send it back to the table. It does not block because the buffered channel is not over-capacity.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 下图接收小电路,谁知道原理
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么