MST

星途 面试题库

面试题:Go中如何高效创建goroutine并避免资源浪费

请阐述在Go语言中创建goroutine时,怎样做可以避免因创建过多goroutine而导致的资源浪费,比如内存消耗过大等问题。请结合代码示例说明,包括但不限于合理设置goroutine的数量、利用sync.WaitGroup控制并发等。
10.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

在Go语言中,可以通过以下几种方式避免因创建过多goroutine而导致的资源浪费:

合理设置goroutine的数量

可以使用工作池(worker pool)的模式来限制同时运行的goroutine数量。例如:

package main

import (
    "fmt"
    "sync"
)

func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
    defer wg.Done()
    for j := range jobs {
        fmt.Printf("Worker %d started job %d\n", id, j)
        result := j * 2
        fmt.Printf("Worker %d finished job %d, result: %d\n", id, j, result)
        results <- result
    }
}

func main() {
    const numJobs = 5
    jobs := make(chan int, numJobs)
    results := make(chan int, numJobs)
    var wg sync.WaitGroup

    const numWorkers = 3
    for w := 1; w <= numWorkers; w++ {
        wg.Add(1)
        go worker(w, jobs, results, &wg)
    }

    for j := 1; j <= numJobs; j++ {
        jobs <- j
    }
    close(jobs)

    go func() {
        wg.Wait()
        close(results)
    }()

    for r := range results {
        fmt.Printf("Result: %d\n", r)
    }
}

在这个例子中,numWorkers 定义了同时运行的goroutine数量,jobs 通道用于传递任务,results 通道用于接收任务的结果。

利用 sync.WaitGroup 控制并发

sync.WaitGroup 用于等待一组goroutine完成。如上面代码中,wg.Add(1) 表示增加一个待完成的goroutine,wg.Done() 表示一个goroutine完成了任务,wg.Wait() 会阻塞直到所有的goroutine都调用了 wg.Done()。这样可以确保在所有任务完成后再关闭相关的通道,避免资源泄露。

避免无节制地创建goroutine

在实际应用中,要根据系统的资源(如CPU、内存等)来动态地创建goroutine。不要在循环等场景下无限制地创建goroutine,而是根据任务队列的长度、系统负载等因素来决定是否需要创建新的goroutine。例如,可以设置一个阈值,当任务队列长度超过阈值时,再考虑创建新的goroutine。

通过以上方法,可以在利用goroutine的并发优势的同时,避免因创建过多goroutine而导致的资源浪费。