Go语言中向超容量的缓冲channel写入数据是否会产生影响?
问题解答:Go语言超容量缓冲channel写入的影响
首先明确结论:向已满的缓冲channel写入数据时,执行写入操作的goroutine会直接阻塞,不会抛出异常、也不会丢失待写入的数据,直到有其他goroutine从该channel读取了数据、腾出空闲缓冲位置,阻塞的goroutine才会被唤醒继续执行写入。
你描述的「子goroutine独立执行写入、主goroutine无需等待子goroutine完成」的场景,确实不会触发死锁:Go的死锁检测只会在所有goroutine都处于阻塞状态时才会触发,该场景下主goroutine可以正常执行读取/其他逻辑,不会出现全局阻塞的情况。
示例代码执行逻辑说明
你提供的代码运行逻辑如下:
- 初始化容量为2的int类型缓冲channel,最多可以暂存2个元素
- 子goroutine启动后依次写入1、2,此时channel被填满,写入4的操作会立刻阻塞,Go调度器会切换执行主goroutine
- 主goroutine依次读取channel中的1、2并打印,此时channel缓冲被清空,阻塞的子goroutine被唤醒继续写入4、6,写入10时因为channel再次被填满会再次阻塞
- 现有代码中主goroutine读完2个元素后就会直接退出,整个程序终止,因此后续的4、6、10不会被输出;如果放开注释中的
close(ch)和range遍历逻辑,就可以顺序读取到所有写入的5个值。
package main import "fmt" func main() { ch := make(chan int, 2) go func (){ ch <- 1 ch <- 2 ch <- 4//在此处阻塞,但调度器会调度其他goroutine执行 ch <- 6 ch <- 10 //close(ch) }() fmt.Println(<-ch) fmt.Println(<-ch) //for v:=range ch{ //fmt.Println(v)//1 2 4 6 10 //} }
额外注意:如果该channel后续始终没有任何goroutine执行读取操作,阻塞的写入goroutine会一直驻留内存无法释放,会造成goroutine泄漏,属于开发中需要避免的问题。
内容的提问来源于stack exchange,提问作者mohammed yaqub
相关产品推荐
相关产品推荐

