面试题答案
一键面试- 避免死锁的方法
- 缓冲设置:合理设置通道的缓冲区大小。如果是无缓冲通道,发送操作会阻塞直到有接收者准备好接收数据,接收操作也会阻塞直到有数据被发送。有缓冲通道则在缓冲区未满时发送操作不会阻塞,在缓冲区未空时接收操作不会阻塞。
- 确保发送和接收的匹配:保证在所有发送操作都完成之前,有足够的接收操作;反之,在所有接收操作完成之前,有足够的发送操作。这可以通过适当的同步机制,如
WaitGroup
来实现。 - 正确关闭通道:在发送端完成数据发送后,要及时关闭通道,这样接收端可以通过
ok
标志判断通道是否关闭,避免无限阻塞在接收操作上。
- 示例代码
package main
import (
"fmt"
"sync"
)
func producer(ch chan int, wg *sync.WaitGroup) {
defer wg.Done()
for i := 0; i < 5; i++ {
ch <- i
}
close(ch)
}
func consumer(ch chan int, wg *sync.WaitGroup) {
defer wg.Done()
for {
data, ok := <-ch
if!ok {
break
}
fmt.Println("Received:", data)
}
}
func main() {
var wg sync.WaitGroup
ch := make(chan int)
wg.Add(2)
go producer(ch, &wg)
go consumer(ch, &wg)
wg.Wait()
}
在上述代码中:
producer
函数向通道ch
发送数据,完成发送后关闭通道。consumer
函数从通道ch
接收数据,当通道关闭时(ok
为false
)退出循环。main
函数使用WaitGroup
等待两个goroutine
完成,确保程序不会提前退出,从而避免死锁。