MST

星途 面试题库

面试题:Go语言sync包中WaitGroup原理与应用

详细解释Go语言sync包中WaitGroup的工作原理。在一个有多个goroutine并发执行任务,并且主线程需要等待所有goroutine完成后再继续执行的场景中,如何正确使用WaitGroup?请编写代码示例展示。如果在使用过程中出现goroutine泄漏,可能是哪些原因导致的?
12.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

WaitGroup工作原理

  1. 计数器机制sync.WaitGroup内部维护一个计数器。当需要等待一组goroutine完成时,通过Add方法将计数器增加指定的值,每个要等待的goroutine对应一个计数单位。
  2. 阻塞与释放:主线程或其他等待的goroutine通过调用Wait方法进入阻塞状态,直到计数器归零。每个goroutine完成任务后,调用Done方法,该方法会将计数器减1。当计数器减为0时,所有因调用Wait而阻塞的goroutine都会被释放,继续执行后续代码。

正确使用示例

package main

import (
    "fmt"
    "sync"
    "time"
)

func worker(id int, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Printf("Worker %d started\n", id)
    time.Sleep(time.Second)
    fmt.Printf("Worker %d finished\n", id)
}

func main() {
    var wg sync.WaitGroup
    numWorkers := 3

    for i := 1; i <= numWorkers; i++ {
        wg.Add(1)
        go worker(i, &wg)
    }

    fmt.Println("Waiting for all workers to finish...")
    wg.Wait()
    fmt.Println("All workers have finished")
}

可能导致goroutine泄漏的原因

  1. 忘记调用Done:如果某个goroutine没有调用Done方法,计数器不会归零,导致Wait永远阻塞,其他goroutine也无法继续执行,造成泄漏。
  2. Addgoroutine启动顺序问题:如果先启动goroutine,后调用Add,可能在Add之前goroutine就已经完成并调用Done,导致计数器变为负数,程序可能会崩溃。
  3. Wait提前返回:如果在所有goroutine完成之前,由于某些逻辑错误,Wait提前返回,可能导致部分goroutine未完成就被遗弃,造成泄漏。