MST

星途 面试题库

面试题:Go WaitGroup 在资源限制型复杂并发场景中的优化运用

假设系统资源有限,同一时间只能允许最多 10 个 goroutine 运行,现在有 100 个任务需要并发执行,每个任务执行时间不定。要求使用 Go WaitGroup 以及合适的机制来保证任务的高效执行,避免资源耗尽,同时尽可能快地完成所有任务。请详细描述设计方案并给出核心代码实现。
47.0万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 设计方案

    • 使用一个有缓冲的通道(buffer channel)来控制并发数量,通道的容量设置为10,这样同一时间最多只有10个任务可以在通道中,也就是最多10个任务同时执行。
    • 使用 WaitGroup 来等待所有任务完成。WaitGroup 的计数器初始化为100,每个任务开始时调用 wg.Add(1),任务结束时调用 wg.Done()
    • 在主函数中,使用一个循环来创建100个任务,每个任务尝试向通道中发送一个信号,获取执行许可,执行完任务后从通道中接收信号,释放执行许可。
  2. 核心代码实现

package main

import (
    "fmt"
    "sync"
)

func task(id int, wg *sync.WaitGroup, sem chan struct{}) {
    defer wg.Done()
    sem <- struct{}{} // 获取执行许可
    defer func() { <-sem }() // 释放执行许可
    // 模拟任务执行时间不定
    fmt.Printf("Task %d is running\n", id)
    // 这里可以替换为实际的任务逻辑
}

func main() {
    var wg sync.WaitGroup
    sem := make(chan struct{}, 10)
    for i := 0; i < 100; i++ {
        wg.Add(1)
        go task(i, &wg, sem)
    }
    wg.Wait()
    fmt.Println("All tasks completed")
}

在上述代码中:

  • task 函数代表具体的任务,接收任务ID、WaitGroup 指针和信号通道。在函数开始时向通道发送信号获取执行许可,结束时从通道接收信号释放许可。
  • main 函数中创建了一个容量为10的信号通道 semWaitGroup。通过循环创建100个 goroutine 来执行任务,每个任务开始前调用 wg.Add(1),最后通过 wg.Wait() 等待所有任务完成。