有缓存的channel与无缓存的channel
在 Go 中,有缓存的 channel(也称为带缓冲的 channel)和普通的 channel(无缓冲 channel)在行为上有显著的区别:
无缓冲 Channel
- 定义:无缓冲 channel 是一种在发送和接收操作时必须匹配的 channel。即,发送操作会被阻塞,直到有接收方准备好接收数据,反之亦然。
- 创建:
make(chan Type)
,例如:make(chan int)
- 特性:
- 发送操作在接收操作之前必须等待。
- 接收操作在发送操作之前必须等待。
- 适用于需要确保同步的场景,比如确保发送者和接收者严格对齐数据流。
有缓存的 Channel
- 定义:有缓存的 channel 具有指定的缓冲区大小,这允许发送操作在没有接收方时继续执行,直到缓冲区满。
- 创建:
make(chan Type, capacity)
,例如:make(chan int, 10)
表示创建一个容量为 10 的缓存 channel。 - 特性:
- 发送操作在缓冲区未满时可以立即完成,而不需要等待接收操作。
- 接收操作在缓冲区不空时可以立即完成,而不需要等待发送操作。
- 可以处理多生产者、多消费者模式,缓冲可以提高性能,减少阻塞。
主要区别
-
阻塞行为:
- 无缓冲 channel:发送和接收操作都必须匹配,发送会阻塞直到有接收方,接收会阻塞直到有发送方。
- 有缓存的 channel:发送操作在缓冲区未满时不会阻塞,接收操作在缓冲区不空时不会阻塞。
-
容量:
- 无缓冲 channel:容量为 0。
- 有缓存的 channel:具有指定的缓冲区大小。
-
用途:
- 无缓冲 channel:适用于需要严格同步的场景。
- 有缓存的 channel:适用于需要处理大量数据的场景,或者需要减少阻塞和等待的场景。
// 无缓冲 channel 示例 ch := make(chan int) go func() { ch <- 1 // 发送会阻塞,直到有接收方 }() fmt.Println(<-ch) // 接收会阻塞,直到有发送方 // 有缓存的 channel 示例 ch := make(chan int, 2) // 缓冲区容量为 2 ch <- 1 // 发送不会阻塞,直到缓冲区满 ch <- 2 // 继续发送不会阻塞 // ch <- 3 // 会阻塞,直到有接收方 fmt.Println(<-ch) // 接收不会阻塞,直到缓冲区有数据 fmt.Println(<-ch) // 接收继续,不会阻塞
question: 无缓冲通道必须在单独goroutine工作,在main中会死锁,这个观点是对是错?
package main import ( "fmt" ) func main() { ch := make(chan int) // 无缓冲 channel // 在 main goroutine 中执行发送和接收操作 ch <- 1 // 这里会阻塞,因为没有接收方 fmt.Println(<-ch) // 这个接收操作也会阻塞,因为发送方没有准备好 // 程序将会在发送操作处死锁 }
answer:
这个观点是对的。无缓冲 channel 的发送和接收操作必须在不同的 goroutine 中进行,否则会导致死锁。原因如下:
无缓冲 Channel 死锁情况
无缓冲 channel 需要发送和接收操作同时进行,否则会出现死锁。具体来说:
- 发送操作:发送方会阻塞,直到接收方准备好接收数据。
- 接收操作:接收方会阻塞,直到发送方发送数据。
如果在同一个 goroutine 中执行发送和接收操作,发送操作会因为没有接收方而阻塞,而接收操作也会因为没有发送方而阻塞。这会导致程序无法继续执行,出现死锁。
解决:
package main import ( "fmt" ) func main() { ch := make(chan int) // 无缓冲 channel go func() { ch <- 1 // 发送数据到 channel }() fmt.Println(<-ch) // 从 channel 中接收数据 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析