我有一个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()
}
go
并发功能非常强大。协调并发非常 困难。幸运的是,go
标准库提供了许多工具来帮助实现这一目标。您可能应该熟悉该context
软件包。
context.Context
在幕后使用完工通道(类似于您的stopChan
),但具有取消链接等其他机制。它们在整个go
标准库中也用于HTTP,数据库和其他阻止类型的请求。
正如@JimB所提到的,sync.Once
在协调生产者/消费者时通常很少需要。chan
s和sync.WaitGroup
s通常就足够了。
无论如何,这是使用context.Context
以下代码的协调修复:
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句