面试题答案
一键面试原理分析
- 无缓冲Channel的问题:无缓冲Channel在发送数据时,必须要有对应的接收方准备好接收,否则发送操作会阻塞。在高并发场景下,若生产者生产数据速度快于消费者消费速度,生产者会频繁阻塞等待消费者接收数据,导致整体性能瓶颈。
- Buffered Channel的优势:Buffered Channel有一定大小的缓冲区,生产者可以先将数据发送到缓冲区,而无需等待消费者立即接收。只有当缓冲区满时,生产者才会阻塞。这允许生产者和消费者在一定程度上异步工作,减少生产者的阻塞时间,提升整体性能。
代码修改
package main
import (
"fmt"
"sync"
"time"
)
func producer(ch chan int, wg *sync.WaitGroup) {
defer wg.Done()
for i := 0; ; i++ {
ch <- i
time.Sleep(time.Millisecond * 1) // 模拟每秒产生1000个数据
}
}
func consumer(ch chan int, wg *sync.WaitGroup) {
defer wg.Done()
for data := range ch {
fmt.Printf("Consumed: %d\n", data)
time.Sleep(time.Millisecond * 10) // 模拟处理每个数据平均需要10毫秒
}
}
func main() {
var wg sync.WaitGroup
// 计算缓冲区大小:消费者每秒能处理100个数据(1000ms / 10ms),生产者每秒产生1000个数据,所以至少需要900大小的缓冲区来避免生产者频繁阻塞
ch := make(chan int, 900)
wg.Add(1)
go producer(ch, &wg)
wg.Add(1)
go consumer(ch, &wg)
time.Sleep(time.Second * 10) // 运行10秒
close(ch)
wg.Wait()
}
在上述代码中,make(chan int, 900)
创建了一个缓冲区大小为900的Buffered Channel。这个大小是基于生产者每秒产生1000个数据,消费者每秒能处理100个数据(1000ms / 10ms)计算得出的,以尽量避免生产者频繁阻塞,提升整体性能。