是否可以使用 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 中关闭一个通道。
我的解决方案如下,但是下面的代码中是否存在竞争条件(它会不会崩溃)?
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 中关闭一个通道。