MST

星途 面试题库

面试题:Go中多个协程向同一Channel发送数据并关闭的正确处理

假设有多个协程需要向同一个Channel发送数据,最后由主协程关闭该Channel。请编写代码实现这个场景,并阐述可能出现的竞态条件以及如何避免。
25.9万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

代码实现(以Go语言为例)

package main

import (
    "fmt"
    "sync"
)

func worker(id int, ch chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 5; i++ {
        ch <- id*10 + i
    }
}

func main() {
    var wg sync.WaitGroup
    ch := make(chan int)
    numWorkers := 3

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

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

    for val := range ch {
        fmt.Println(val)
    }
}

可能出现的竞态条件及避免方法

  1. 竞态条件
    • 多个协程同时向Channel发送数据时,虽然Go语言的Channel本身是线程安全的,但是在关闭Channel时可能出现竞态条件。如果主协程在所有工作协程还未完成发送数据时就关闭了Channel,那么还未发送的数据将会丢失。
  2. 避免方法
    • 使用sync.WaitGroup。在每个工作协程开始时调用wg.Add(1),在工作协程结束时调用wg.Done()。主协程通过wg.Wait()等待所有工作协程完成后再关闭Channel,这样可以确保所有数据都被发送到Channel中。