面试题答案
一键面试合理设置通道缓冲区大小预防Goroutine卡住的方法
- 理解缓冲区作用:
- 未缓冲通道在发送和接收操作时需要对应的接收和发送操作同时准备好,否则会阻塞。而缓冲通道允许在没有对应接收操作时,先发送一定数量的数据到缓冲区。
- 合理设置缓冲区大小要考虑应用场景中数据产生和消费的速度。如果数据产生速度较快,消费速度较慢,需要设置较大的缓冲区来避免生产者Goroutine过早阻塞;如果两者速度相近,可以设置较小的缓冲区甚至使用未缓冲通道。
- 根据场景估算:
- 例如在一个生产者 - 消费者模型中,如果生产者在短时间内会产生大量数据,且消费者处理每个数据需要一定时间,需要估算大概可能产生的数据量,然后设置一个稍大于该估算值的缓冲区大小。
代码示例
package main
import (
"fmt"
)
func producer(ch chan int) {
for i := 0; i < 10; i++ {
ch <- i
fmt.Printf("Produced: %d\n", i)
}
close(ch)
}
func consumer(ch chan int) {
for val := range ch {
fmt.Printf("Consumed: %d\n", val)
}
}
func main() {
// 设置缓冲区大小为5
ch := make(chan int, 5)
go producer(ch)
go consumer(ch)
// 防止主函数退出
select {}
}
在上述代码中,我们将通道 ch
的缓冲区大小设置为5。生产者可以先向通道发送5个数据而不会阻塞,消费者在消费数据的同时,生产者可以继续发送数据,这样减少了生产者Goroutine卡住的可能性。