首頁  >  文章  >  後端開發  >  從 Goroutine 收集結果時如何避免死鎖?

從 Goroutine 收集結果時如何避免死鎖?

Patricia Arquette
Patricia Arquette原創
2024-11-06 14:22:02650瀏覽

How to Avoid Deadlocks When Gathering Results from Goroutines?

使用 Goroutine 進行資料處理

在 Go 中,goroutine 是一種輕量級線程,可以實現任務的並發執行。使用 goroutine 時,在處理後正確收集結果以避免死鎖非常重要。

問題陳述

考慮以下程式碼片段:

sampleChan := make(chan sample)
var wg sync.WaitGroup

// Read from contents list
for i, line := range contents {
    wg.Add(1)
    // Process each item with a goroutine and send output to sampleChan
    go newSample(line, *replicatePtr, *timePtr, sampleChan, &wg)
}
wg.Wait()

// Read from sampleChan and put into a slice
var sampleList []sample
for s := range sampleChan {
    sampleList = append(sampleList, s)
}
close(sampleChan)

此程式碼嘗試使用goroutine 處理清單中的項目並將結果收集到切片中。然而,它遇到了死鎖錯誤,因為在收集結果之前通道已關閉。

解決方案

要解決這個問題,我們可以非同步關閉通道工人們已經完成加工。以下是修正後的程式碼:

for i, line := range contents {
    wg.Add(1)
    // Process each item with a goroutine and send output to sampleChan
    go newSample(line, *replicatePtr, *timePtr, sampleChan, &wg)
}

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

for s := range sampleChan {
  ..
}

此程式碼啟動處理項目並將結果傳送到sampleChan 的goroutines。同時,它還啟動另一個 goroutine,等待所有工作執行緒完成,然後關閉通道。這可以確保在通道關閉之前收集所有結果。

替代解決方案

為了更好的程式碼可讀性和可測試性,建議使用同步 newSample 函數和句柄主 Goroutine 中的並發性。

for i, line := range contents {
    wg.Add(1)
    go func(line string) {
        defer wg.Done()
        sampleChan <- newSample(line, *replicatePtr, *timePtr)
    }(line)
}

這種方法使並發原語保持在地化,簡化程式碼維護並降低錯誤風險。

以上是從 Goroutine 收集結果時如何避免死鎖?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn