【问题标题】:Is it possible to safely close a channel once from multiple goroutines using select?是否可以使用 select 从多个 goroutine 中安全地关闭一个通道?
【发布时间】:2021-07-07 10:49:00
【问题描述】:

我的解决方案如下,但以下代码中是否存在竞争条件(它会恐慌)吗?

c := make(chan struct{})

for i := 0; i < 1000000; i++ {
    go func() {
        select {
        case <-c:
        default:
            close(c)
        }
    }()
}

我会假设是的,但是 go test -race 没有检测到它,并且凭经验我无法让它恐慌。

【问题讨论】:

  • 这可能会多次关闭频道,是的。

标签: go concurrency channel goroutine


【解决方案1】:

你启动了多个没有同步的 goroutine。所以它们同时运行。可能会发生其中 2 个并行评估 &lt;-c 的情况,因为这是一个阻塞操作,所以两者都会选择 default 情况。此时,这两个 goroutine 都会尝试关闭通道,只有一个会成功,另一个会恐慌:您无法关闭已关闭的通道。

这不是竞态条件,因为您不会同时读取/修改变量,但尝试关闭已关闭的通道会导致运行时恐慌(因此竞态检测器永远不会捕捉到这一点)。

当有多个 goroutine 在一个通道上发送时,等待所有完成,然后在单个 goroutine 中关闭通道。不要试图从多个 goroutine 中关闭一个通道。

【讨论】:

  • 在我的例子中,上下文是一个结构上的 Close 函数,可以从不同的 goroutine 调用。我想我必须使用同步。然后。
猜你喜欢
  • 2019-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-29
  • 2020-08-02
  • 2012-06-14
  • 2011-05-21
相关资源
最近更新 更多