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

Go代码死锁报错:所有goroutine休眠,求排查原因

Go代码死锁原因及修复方案

死锁根源

你的代码存在两个核心问题导致死锁:

  1. 无缓冲Channel的阻塞循环:goroutine执行ch <- freq时,无缓冲Channel必须有接收方才能完成发送。但主逻辑先执行wg.Wait()等待所有goroutine结束,此时所有goroutine都卡在发送Channel的步骤(没人接收),主goroutine又卡在等待WaitGroup完成,双方互相阻塞形成死锁。
  2. Channel未关闭导致后续阻塞:哪怕改用带缓冲Channel,所有goroutine发送完数据后,主goroutine的for n := range ch会一直等待新数据,因为Channel没被关闭,最终还是会触发死锁。

修复后的代码

package main

import (
    "fmt"
    "sync"
)

func findMax(nums []int32) int32 {
    max := nums[0]
    for _, n := range nums {
        if n > max {
            max = n
        }
    }
    return max
}

func findFreq(nums []int32, n int32) int32 {
    mp := make(map[int32]int32)
    for _, num := range nums {
        mp[num]++ // 简化map计数逻辑,和原代码效果一致
    }
    if f, ok := mp[n]; ok {
        return f
    }
    return -1
}

func performWork(ch chan int32, nums []int32, q int32, wg *sync.WaitGroup) {
    defer wg.Done()
    seg := nums[q-1:]
    max := findMax(seg)
    freq := findFreq(seg, max)
    ch <- freq
}

func frequencyOfMaxValue(numbers []int32, q []int32) []int32 {
    res := []int32{}
    var wg sync.WaitGroup
    // 创建大小等于查询数量的带缓冲Channel,避免goroutine发送时阻塞
    ch := make(chan int32, len(q))
    
    for _, query := range q {
        wg.Add(1)
        go performWork(ch, numbers, query, &wg)
    }

    // 启动单独goroutine,等待所有任务完成后关闭Channel
    go func() {
        wg.Wait()
        close(ch)
    }()

    // 读取Channel中所有数据,Channel关闭后range会自动退出
    for n := range ch {
        res = append(res, n)
    }
    return res
}

func main() {
    nums := []int32{5, 4, 5, 3, 2}
    queries := []int32{1, 2, 3, 4, 5}
    fmt.Println(frequencyOfMaxValue(nums, queries))
}

关键修复点

  • 使用带缓冲Channel,大小与查询数量一致,保证每个goroutine都能顺利发送数据而不阻塞。
  • 新增匿名goroutine,在WaitGroup完成后关闭Channel,让主goroutine的range循环在读取完所有数据后自动终止。
  • 简化了findFreq的map计数逻辑,保持原业务逻辑不变的同时提升可读性。

内容的提问来源于stack exchange,提问作者kharlezaizen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 20:15:55