MST

星途 面试题库

面试题:Go中sync包实现协程同步的复杂场景应用

假设有一个场景,需要启动多个协程去处理一批数据,每个协程处理一部分数据后会生成一个结果,最终需要将所有协程的结果汇总。在这个过程中,要确保所有协程处理完成后才进行结果汇总操作,同时要避免数据竞争问题。请使用sync包相关工具(如Mutex、WaitGroup等)编写Go代码来实现该场景,并解释代码中每个同步工具的作用。
45.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

import (
    "fmt"
    "sync"
)

func main() {
    data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    var wg sync.WaitGroup
    var mu sync.Mutex
    results := make([]int, 0)

    numCoroutines := 3
    chunkSize := (len(data) + numCoroutines - 1) / numCoroutines

    for i := 0; i < numCoroutines; i++ {
        start := i * chunkSize
        end := (i + 1) * chunkSize
        if end > len(data) {
            end = len(data)
        }

        wg.Add(1)
        go func(s, e int) {
            defer wg.Done()
            localResult := 0
            for _, v := range data[s:e] {
                localResult += v
            }
            mu.Lock()
            results = append(results, localResult)
            mu.Unlock()
        }(start, end)
    }

    wg.Wait()
    fmt.Println("Final results:", results)
}

同步工具的作用

  1. WaitGroup:
    • wgsync.WaitGroup 类型的变量。
    • wg.Add(1) 用于通知 WaitGroup 有一个新的协程开始工作,这里每启动一个协程就调用一次 Add(1)
    • defer wg.Done() 表示当前协程工作完成,会减少 WaitGroup 的计数。
    • wg.Wait() 会阻塞当前 goroutine,直到 WaitGroup 的计数归零,即所有协程都调用了 Done(),确保所有协程处理完成后才进行后续操作。
  2. Mutex:
    • musync.Mutex 类型的变量。
    • mu.Lock() 用于锁定互斥锁,防止其他协程同时访问共享资源 results
    • mu.Unlock() 用于解锁互斥锁,允许其他协程访问共享资源 results。这样就避免了多个协程同时写入 results 导致的数据竞争问题。