【发布时间】:2019-07-11 05:27:41
【问题描述】:
我有一个stopChan 来通知发件人关闭频道,还有一个sync.Once 来确保只有一个发件人可以关闭频道,但我仍然收到“在关闭的频道上发送”的恐慌,为什么?
func muitiSenderClose() {
const SenderNum = 3
wg := sync.WaitGroup{}
wg.Add(SenderNum)
intChan := make(chan int)
stopChan := make(chan struct{})
once := sync.Once{}
for i := 0; i < SenderNum; i++ {
go func(i int) {
defer wg.Done()
needStop := false
for {
select {
case <-stopChan:
needStop = true
case intChan <- 1:
case intChan <- 2:
case intChan <- 3:
}
if needStop {
break
}
}
once.Do(func() {
fmt.Printf("%d want to close chan\n",i)
close(intChan)
})
fmt.Println("End. [sender] %id", i)
}(i)
}
sum := 0
for e := range intChan {
fmt.Printf("Receive %d\n", e)
sum += e
if sum > 10 {
close(stopChan)
fmt.Printf("Got %d\n", sum)
break
}
}
fmt.Println("End. [receiver]")
wg.Wait()
}
【问题讨论】:
-
所有发件人完成后关闭通道。您需要
sync.Once来关闭频道这一事实应该表明它位于错误的位置。您还有数据竞赛,请务必检查竞赛检测器。 -
你有多个 goroutines 都在
intChan上发送。他们不能都关闭它。共享频道的发件人需要等到所有发件人发送完毕才能关闭。