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

如何实现Goroutine任务进度监控并解决死锁问题?

问题排查与修复方案

关键问题分析

  • 函数参数类型错误:
    • task函数的registers string[]类型不匹配,调用时传入的是int切片,应改为[]int。
    • status <-chan int是只读通道,但函数需要向通道发送数据,应改为chan<- int(只写通道)。
  • 切片范围计算错误:
    循环中分割切片时,(partial*i)+1会跳过每个分段的第一个元素,导致总处理元素数量不足16个,正确分段应为registers[partial*i : partial*(i+1)]。
  • 通道接收逻辑错误:
    原代码的for len(status) > 0 && <-status > 0会在每次循环中两次读取通道值(一次在条件判断,一次在count += <-status),导致统计结果错误;且当通道暂时为空时会直接退出循环,无法等待所有任务完成。
  • 未等待所有Goroutine完成:
    无同步机制等待所有task Goroutine执行完毕,主Goroutine可能提前退出,导致部分任务未处理,甚至引发Goroutine阻塞泄漏。

修复后的完整代码

import (
    "fmt"
    "log"
    "net/http"
    "sync"
)

func task(registers []int, status chan<- int, wg *sync.WaitGroup) {
    defer wg.Done()
    for range registers {
        status <- 1 // 每处理一个元素,发送1表示完成一个任务单元
    }
}

func main() {
    status := make(chan int, 16) // 缓冲设为16,避免Goroutine因通道满阻塞

    http.HandleFunc("/process", func(w http.ResponseWriter, r *http.Request) {
        registers := [16]int{1, 6, 56, 10, 50, 60, 10, 5, 9, 8, 10, 25, 56, 10, 20, 365}
        partial := 4
        var wg sync.WaitGroup

        // 启动4个Goroutine处理分段任务
        for i := 0; i < 4; i++ {
            start := partial * i
            end := partial * (i + 1)
            wg.Add(1)
            go task(registers[start:end], status, &wg)
        }

        // 单独启动Goroutine,等待所有任务完成后关闭通道
        go func() {
            wg.Wait()
            close(status)
        }()

        // 统计总完成任务数
        count := 0
        for num := range status {
            count += num
            // 可选:实时输出进度到HTTP响应(流式输出)
            // fmt.Fprintf(w, "Current progress: %d/16\n", count)
            // w.(http.Flusher).Flush()
        }

        fmt.Fprintf(w, "Processed loop status: %d/16", count)
    })

    fmt.Println("Server is running")
    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatal(err)
    }
}

修复细节说明

  1. 修正参数类型:
    匹配切片类型与通道读写权限,避免编译错误与逻辑冲突。
  2. 修复切片分段:
    用start和end变量确保每个分段包含4个元素,覆盖全部16个任务。
  3. 引入WaitGroup同步:
    用sync.WaitGroup跟踪所有Goroutine状态,确保主逻辑在所有任务完成后再统计结果;单独启动Goroutine关闭通道,避免主逻辑阻塞。
  4. 优化通道接收逻辑:
    用for num := range status遍历通道,确保接收所有任务结果,统计准确。若需要实时展示进度,可开启注释部分的流式输出代码。
  5. 调整通道缓冲:
    缓冲设为16,确保所有任务结果能无阻塞写入,避免Goroutine阻塞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 19:12:35