首頁 > 後端開發 > Golang > 主體

我們如何正確地重複使用多個 Go 通道以避免競爭條件和資料遺失?

Patricia Arquette
發布: 2024-11-23 16:42:18
原創
150 人瀏覽過

How Can We Correctly Multiplex Multiple Go Channels to Avoid Race Conditions and Data Loss?

多路復用通道

本文介紹了一個多路復用器函數,旨在將通道數組的輸出合併到單一通道中。然而,所提供的實作存在一些阻礙其功能的問題。

原始程式碼:

func Mux(channels []chan big.Int) chan big.Int {
    // Count down as each channel closes. When hits zero - close ch.
    n := len(channels)
    // The channel to output to.
    ch := make(chan big.Int, n)

    // Make one go per channel.
    for _, c := range channels {
        go func() {
            // Pump it.
            for x := range c {
                ch <- x
            }
            // It closed.
            n -= 1
            // Close output if all closed now.
            if n == 0 {
                close(ch)
            }
        }()
    }
    return ch
}
登入後複製

實作中的錯誤:

從多個Goroutine 關閉: n 變數在多個Goroutine 之間共享,並由每個Goroutine 更新當goroutine 偵測到通道關閉時。當多個 goroutine 嘗試同時存取和更新 n 時,這可能會導致競爭條件和意外行為。

不正確的通道捕獲:循環中創建的goroutine 每個捕獲相同的通道(最後一個)通道的元素),因為每次迭代時都會為c 分配通道的值,而不是傳給goroutine

已解決的問題:

為了解決這些問題,修改後的程式碼採用了更安全的技術:

使用WaitGroup :sync.WaitGroup 用於追蹤goroutine 的完成情況。每個 Goroutine 在完成泵送資料後都會向 WaitGroup 發出訊號,主 Goroutine 會等待所有 Goroutine 完成後再關閉輸出通道。

正確的通道捕獲:每個 Goroutine 都會透過通道它應該在 lambda 函數中監聽,確保每個 goroutine 正確監控其分配的通道。

改進的輸出: 修改後的程式碼產生預期的輸出,其中所有通道以均勻分佈的方式貢獻於輸出通道。原始輸出中觀察到的順序饋送被消除。

其他注意事項:

  • 在沒有並發控制機制的情況下,使用GOMAXPROCS != 1 可以加劇共享變數存取的問題,導致意外結果。
  • WaitGroup 方法可確保僅當所有通道的所有資料都已處理完畢時,輸出通道才會關閉。如果沒有 WaitGroup,主 Goroutine 可能會過早關閉輸出通道,導致資料遺失。

以上是我們如何正確地重複使用多個 Go 通道以避免競爭條件和資料遺失?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板