Go语言递归并行归并排序实现出现死锁问题求助
问题原因分析
你的代码触发死锁的核心问题是通道发送与接收的顺序错误:
- 子goroutine执行
orderedLeft <- left和orderedRight <- right时,主goroutine正卡在wg.Wait()等待子goroutine完成,此时没有任何接收方在监听通道。 - Go的无缓冲通道发送操作会持续阻塞,直到有接收方准备好接收数据。这就导致子goroutine卡在发送步骤无法结束,主goroutine卡在等待子goroutine完成,形成循环等待的死锁状态。
修复方案
方案一:移除WaitGroup,直接用通道传递结果(更简洁)
不需要同时混用WaitGroup和通道,直接通过goroutine+通道来同步子任务结果:
func mergeSort(arr []int) []int { if len(arr) <= 1 { return arr } mid := len(arr) / 2 leftCh := make(chan []int) rightCh := make(chan []int) go func() { leftCh <- mergeSort(arr[:mid]) }() go func() { rightCh <- mergeSort(arr[mid:]) }() left := <-leftCh right := <-rightCh return merge(left, right) }
方案二:调整接收与Wait的顺序(保留WaitGroup)
如果一定要用WaitGroup,需要把通道接收操作移到wg.Wait()之前,让子goroutine发送数据时主goroutine已经在等待接收,避免阻塞:
func mergeSort(arr []int) []int { if len(arr) <= 1 { return arr } mid := len(arr) / 2 orderedLeft := make(chan []int) orderedRight := make(chan []int) var wg sync.WaitGroup wg.Add(2) go func() { defer wg.Done() orderedLeft <- mergeSort(arr[:mid]) }() go func() { defer wg.Done() orderedRight <- mergeSort(arr[mid:]) }() // 先接收通道数据,再等待goroutine完成 leftRes := <-orderedLeft rightRes := <-orderedRight wg.Wait() close(orderedLeft) close(orderedRight) return merge(leftRes, rightRes) }
额外优化提示
- 归并非得拆分到最小粒度才并发,goroutine创建有开销。可以设置阈值(比如数组长度小于1000时),直接用串行归并排序,避免过多goroutine拖慢性能。
- 这里用无缓冲通道足够,不需要额外设置缓冲,因为是一对一的发送与接收场景。
内容的提问来源于stack exchange,提问作者Hugo-Cruz
相关产品推荐
相关产品推荐

