下面这段代码加了锁为什么偶尔还是会报:panic: send on.closed channel
package main
import (
"context"
"fmt"
"sync"
)
var lock sync.Mutex
func main() {
// channel 初始化
c := make(chan int, 10)
// 用来 recevivers 同步事件的
wg := sync.WaitGroup{}
// 上下文
ctx, cancel := context.WithCancel(context.TODO())
// 专门关闭的协程
wg.Add(1)
go func() {
defer wg.Done()
lock.Lock()
cancel()
// ... 某种条件下,关闭 channel
close(c)
lock.Unlock()
}()
// senders(写端)
for i := 0; i < 10; i++ {
wg.Add(1)
go func(ctx context.Context, id int) {
defer wg.Done()
lock.Lock()
select {
case <-ctx.Done():
fmt.Println("aaa")
return
case c <- id: // 入队
// ...
}
lock.Unlock()
}(ctx, i)
}
// 等待所有的 receivers 完成;
wg.Wait()
for i2 := range c {
fmt.Println(i2)
}
}
https://go.dev/ref/spec#Selec...
https://go.dev/ref/spec#Send_...
case <-ctx.Done():
并不能阻止case c<-id:
的执行。因为即使c
被关闭了,他依然 "can proceed" ,于是会在<-ctx.Done()
与c<-id
中随机选择一个执行。