【问题标题】:Go: using one channels to receive results from multiple goroutinesGo:使用一个通道从多个 goroutine 接收结果
【发布时间】:2022-01-27 10:56:58
【问题描述】:

我有一个包含数千条记录的 CSV 文件。 我在一个 goroutine 中处理每条记录,我想将所有已处理记录的结果收集到一个切片中,以便将它们写在另一个文件中。 我的代码的简化版本是:

var wg sync.WaitGroup

func main() {
    c := make(chan string, 1)
    csvfile, err := os.Open("data.csv")
    reader := csv.NewReader(bufio.NewReader(csvfile))
    //...
    for {
        line, err := reader.Read()
        // ...
        wg.Add(1)
        go processRecord(line, c)
    }
    //...
    results := make([]string, 0)
    for r := range c { // ERROR HERE: fatal error: all goroutines are asleep - deadlock!
        results = append(results , r)
    }
    // write results to file
    wg.Wait()
    close(c)
}

func processRecord(data []string, c chan string) {
    defer wg.Done()
    // ...
    c <- *result
}

在 for 循环中,我得到了所有结果,但在得到最后一个结果后循环继续,我得到这个错误:

fatal error: all goroutines are asleep - deadlock! 

这段代码有什么问题?我在 SO 上尝试了不同的 QA,但没有任何成功。

【问题讨论】:

    标签: go goroutine


    【解决方案1】:

    for 循环只会在通道关闭后终止。您在 for 循环终止后关闭通道,因此出现死锁。

    您可以通过将 for 循环放入 goroutine 来修复:

    results := make([]string, 0)
    done:=make(chan struct{})
    go func() {
        for r := range c {
            results = append(results , r)
        }
        close(done)
    }()
    wg.Wait()
    close(c)
    <-done
    // read results
    

    【讨论】:

    • 这种模式是不是也需要一个 WaitGroup 或 channel 读取来与 r​​esults goroutine 同步?
    • @DanielFarrell,已经有一个等待组来等待所有的 goroutine。为什么需要与结果 goroutine 同步?
    • 否则在 main 函数和结果函数之间会存在访问 results 的竞争条件?
    • @DanielFarrell,你是对的。由于原始帖子没有使用result,因此没有种族,但假设一切都完成后将使用results,因此需要额外的保护来防止种族。我将其添加到答案中。
    【解决方案2】:
    for r := range c { // ERROR HERE: fatal error: all goroutines are asleep - deadlock!
        mutex.Lock()
        results = append(results , r)
        mutex.Unlock()
    }
    

    goroutines 睡着了——死锁!因为它是同时写的。使用 Mutex 可以处理这个异常

    【讨论】:

    • 不,这不是原因。互斥锁不会解决死锁问题。
    猜你喜欢
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 2020-08-02
    • 1970-01-01
    • 2015-06-03
    • 2018-10-23
    • 2016-03-02
    • 2019-10-08
    相关资源
    最近更新 更多