You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 05:40:05