【问题标题】:Go channels publish, receive and go routine schedulingGo 频道发布、接收和 go 例程调度
【发布时间】:2020-12-28 16:09:20
【问题描述】:

我有以下 go 脚本,我对读取数据的通道和 go 例程的执行顺序有疑问。

package main

import "fmt"

func squares(c chan int) {
    fmt.Println("started squares goroutine...")
    for num := range c {
        //num := <-c
        fmt.Println(num * num)
    }
    fmt.Println("exiting squares goroutine...")
}

func main() {
    fmt.Println("main() started")
    c := make(chan int, 3)

    go squares(c)

    c <- 1
    printChannel(c)
    c <- 2
    printChannel(c)
    c <- 3
    printChannel(c)
    c <- 4
    fmt.Println("after publish 4")
    printChannel(c)
    c <- 5
    fmt.Println("after publish 5")
    printChannel(c)
    c <- 6
    printChannel(c)
    c <- 7
    printChannel(c)
    c <- 8
    printChannel(c)

    fmt.Println("main() stopped")
}

func printChannel(c chan int) {
    fmt.Println("length: ",len(c))
    fmt.Println("capacity: ",cap(c))
    
}

输出:

main() started
length:  1
capacity:  3
length:  2
capacity:  3
length:  3
capacity:  3
started squares goroutine...
1
4
9
16
after publish 4
length:  0
capacity:  3
after publish 5
length:  0
capacity:  3
length:  1
capacity:  3
length:  2
capacity:  3
length:  3
capacity:  3
main() stopped

问题:

  1. 创建的通道 ch 的容量为 3,但在将 4 发布到通道之前,不会在方块 go 例程中读取通道,如果容量为 3,则通道中存储了 4

  2. 从channel读取完所有数字后,再次将数字5发布到channel,但是channel的长度还是0,为什么?

代码的Goplayground链接:https://play.golang.org/p/TmCcZt5n58f

【问题讨论】:

    标签: go concurrency channel goroutine


    【解决方案1】:

    无法保证 goroutine 的执行顺序,也无法保证 goroutine 何时中断(I/O,包括打印到 stdout,将是重新调度的最常见原因)。

    对于您的第一个问题:您可以看到 16 在 after publish 4 之前打印。这意味着squares goroutine 在主 goroutine 开始打印信息之前从通道读取并打印了正方形。当主 goroutine 尝试打印通道的长度时,4 已经消失了。

    同样,在发送5 到频道后,squares goroutine 已经收到了,但还没有打印出来。它在打印之前被中断。这意味着频道又是空的,但我们还没有看到25。

    如果您多次运行示例,您会看到不同的输出。有时squares goroutine 会一直上升到64,有时不会。这是完全正常的。在普通代码中,您需要确保在退出之前等待数据被使用,并且您不会依赖于不同 goroutine 的执行顺序或时间。

    【讨论】:

      猜你喜欢
      • 2018-02-18
      • 1970-01-01
      • 2021-10-20
      • 1970-01-01
      • 2011-03-04
      • 2014-06-27
      • 2012-01-04
      • 2021-12-05
      • 2019-10-09
      相关资源
      最近更新 更多