电话
400 9058 355
Go 中 channel 作为函数参数时本身不需要加锁,因其内部已实现并发安全;向 channel 发送(ch

Go 的 channel 是并发安全的:向 channel 发送(ch )和接收()操作天然原子,底层由 runtime 用 mutex 保护。只要不把 channel 和其他非并发安全的数据(比如 map、slice、自定义 struct 字段)混在一起共享,单独传 channel 给多个 goroutine 用完全没问题。
常见误解是“既然多 goroutine 在用,就得加锁”,但这是把 channel 错当成普通变量了。它本质是个带同步语义的通信原语,不是需要手动保护的临界资源。
典型场景是把 channel 和非并发安全状态耦合使用,比如:
map[string]chan int,但没保护 map 本身的读写 —— 这里要锁的是 map,不是 chan int
close(ch),同时其他 goroutine 还在发/收 —— 这属于逻辑错误(panic: send on closed channel),不是锁能解决的,得靠关闭协议(如用 sync.Once 或额外 done channel)channel 的“并发安全”不等于“任意关闭都安全”。关键点在于:
chan(只写)或 (只读),编译器会帮你挡住非法操作,比裸指针安全得多
所以比起加锁,更该花精力设计 channel 生命周期:谁创建、谁关闭、是否需要 context.Context 控制退出。
比如实现一个带缓冲池的 channel 工厂,内部维护 freeChans []*Channel 切片,这时对切片的 push/pop 就必须加 sync.Mutex —— 因为 []*Channel 本身不是并发安全的。
再比如封装 channel 的 wrapper struct:
type SafeChan struct {
mu sync.RWMutex
ch chan int
closed bool
}
这个 mu 不是为了保护 ch 的收发,而是为了保护 closed 标志位和防止重复 close。真正发数据时,仍直接走 c.ch ,不经过锁。
复杂点往往不在 channel 本身,而在你试图用它去模拟队列、信号量或状态机时,悄悄混入了非并发安全的辅助数据结构。
邮箱:8955556@qq.com
Q Q:8955556
本文详解如何将Go官方present工具(用于生成HTML5...
PySNMP在不同版本中对SNMP错误状态(errorSta...
time.Sleep仅阻塞当前goroutine,其他gor...
PHPfopen()创建含特殊符号的文件名失败主因是操作系统...
WooCommerce中通过代码为分组产品动态聚合子商品的属...
io.ReadFull返回io.ErrUnexpectedE...
本文详解Yii2中控制器向视图传递ActiveRecord数...
本文详解为何通过wp_set_object_terms()为...
Pytest中使用@mock.patch类装饰器会导致补丁泄...
带缓冲的channel是并发安全的FIFO队列;make(c...