是否可以使用 select 从多个 goroutine 中安全地关闭一次通道?

Is it possible to safely close a channel once from multiple goroutines using select?

我的解决方案如下,但是下面的代码中是否存在竞争条件(它会不会崩溃)?

c := make(chan struct{})

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

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

您在没有同步的情况下启动了多个 goroutine。所以他们 运行 同时。可能会发生其中 2 个并行计算 <-c 的情况,因为这是一个阻塞操作,所以两者都会选择 default 的情况。那时,这两个 goroutine 都会尝试关闭通道,只有一个会成功,另一个会 panic:你无法关闭已关闭的通道。

这不是竞争条件,因为您不会同时 read/modify 变量,但尝试关闭已关闭的通道是 运行 时间恐慌(因此竞争检测器永远不会捕捉到这一点) .

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