【问题标题】:Multiple Goroutines write to a channel at the same time problem多个 Goroutines 同时写入一个通道的问题
【发布时间】:2022-11-02 10:04:55
【问题描述】:

我正在学习 Go 的并发模型,并从“Learning Go”一书中遇到了一个例子 - Oreilly。 在下面的示例中,“r := <-result”会阻塞,直到任何 Goroutine 写入结果通道,并且由于结果是无缓冲通道,后续从其他 Goroutine 写入结果将阻塞,直到结果通道再次为空。我的问题是,如果有 2 个 Goroutines 并行运行并同时写入结果通道(结果当时为空),在这种情况下,Go 运行时如何解决问题?

func searchData(s string, searchers []func(string) []string) []string {
    done := make(chan struct{})
    result := make(chan []string)
    for i, searcher := range searchers {
        go func(searcher func(string) []string) {
            select {
            case result <- searcher(s):
            case <-done:
            }
        }(searcher)
    }
    r := <-result
    close(done)
    return r
}

【问题讨论】:

    标签: go parallel-processing channel goroutine


    【解决方案1】:

    当多个 goroutine 同时写入同一个无缓冲通道时,它们都会阻塞,直到另一个 goroutine 从该通道读取。当一个 goroutine 从通道读取数据时,其中一个等待的 goroutine 将继续写入并继续,而其他的 goroutine 继续等待。 writer goroutine 将被随机选择。

    这以相同的方式推广到多个读取器和多个写入器。如果多个 goroutine 在多个 goroutine 写入时从通道读取,则随机选择的 goroutine 将能够向另一个随机选择的 goroutine 发送消息。

    【讨论】:

    • 是的,我知道如果结果通道已经保存了一个值并且有 2 个 goroutine 并行运行写入它,那么两者都会阻塞。但我的意思是如果结果为空并且有 2 个 goroutine 在 2 个独立的 CPU 内核中并行运行;都写入结果。那时会发生什么? Go 运行时如何处理这种情况?谢谢你。
    • 通道无缓冲。它不能保存一个值。只有当另一个 goroutine 从通道读取时,才会继续写入。如果两个 goroutine 正在等待写入,并且此时如果一个 goroutine 从通道中读取,则其中一个 goroutine 将写入并继续,另一个将保持阻塞状态。
    【解决方案2】:

    你可以在 go runtime 中阅读 channel 的源代码。通过锁定频道去解决冲突。每当遇到并发问题时,锁定数据以供独占使用是通常的解决方案。

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
    猜你喜欢
    • 2015-06-03
    • 2019-10-08
    • 2022-11-05
    • 1970-01-01
    • 2017-03-28
    • 2014-08-01
    • 2016-03-25
    • 1970-01-01
    • 2013-07-10
    相关资源
    最近更新 更多