多路復用通道
本文介紹了一個多路復用器函數,旨在將通道數組的輸出合併到單一通道中。然而,所提供的實作存在一些阻礙其功能的問題。
原始程式碼:
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 正確監控其分配的通道。
改進的輸出: 修改後的程式碼產生預期的輸出,其中所有通道以均勻分佈的方式貢獻於輸出通道。原始輸出中觀察到的順序饋送被消除。
其他注意事項:
以上是我們如何正確地重複使用多個 Go 通道以避免競爭條件和資料遺失?的詳細內容。更多資訊請關注PHP中文網其他相關文章!