【问题标题】:Why goroutine channel does this?为什么 goroutine 频道会这样做?
【发布时间】:2020-05-24 09:32:20
【问题描述】:

我是 golang 的新手。我正在尝试了解频道的工作原理,但这确实令人困惑。

我评论了我的问题。有人可以向我解释为什么这段代码会以这种奇怪的方式表现吗?

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
    c := make(chan int)
    go pokeVals(slice, c)

    fmt.Println(slice)
    fmt.Println("start")
    <-c // why 2 "poke"s here?
    fmt.Println("-")
    <-c // why 0 "poke"s?
    //<-c // But if uncommented - 2 more "pokes" here

    fmt.Println("end")
}

func pokeVals(values []int, c chan int) {
    for _, val := range values {
        fmt.Println("poke")
        c <- val
    }
    fmt.Println("overpoked")
}

Golang 操场链接:https://play.golang.org/p/u__cVyUbNJY

【问题讨论】:

    标签: go channel goroutine


    【解决方案1】:

    Goroutines 并发运行。它们的调度方式不在您的掌控之中,唯一可以保证的就是您是否使用了同步,例如通道、等待组或其他同步原语。

    main() 启动一个goroutine,它在循环中发送c 上的值。但在发送每个值之前,它首先打印"poke"。因此,即使您没有收到来自c 的信息,您也可能会看到打印了一个"poke"。如果你确实收到了来自c 的值,那么这个goroutine 中的循环可以继续下一次迭代,再次打印"poke",它可能会立即这样做,甚至在main() goroutine 开始打印"-" 之前.这就是你所经历的。

    原始版本中的main() goroutine(第三个&lt;-c 被注释掉)终止(在打印"end" 之后)。一旦main() 返回,您的应用程序就会结束,它不会等待其他 goroutine 完成。这就是你所经历的。详情请见No output from goroutine

    如果您取消注释第三个&lt;-c,那么main() 必须在c 上等待另一个发送,这意味着它必须在此之前等待"poke" 打印。一旦pokeVals() 的goroutine 能够在c 上发送另一个值,它可能会在下一次迭代的循环中再次打印"poke"(如果这被安排在从main() 返回之前),这就是你所经历的.

    您是否看到另外 2 个 "poke" 的打印不是确定性的,其中 1 个或 2 个都是有效结果。

    【讨论】:

    • 是的,就是这样。我想我们可以称它为我在算法中的错误,而不是 goroutines 的奇怪之处。如果我们在 'c
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-06
    • 2021-09-22
    • 1970-01-01
    • 2017-07-14
    • 2015-07-07
    相关资源
    最近更新 更多