チャネルの多重化
この記事では、チャネルの配列の出力を 1 つのチャネルにマージすることを目的としたマルチプレクサ関数について説明します。ただし、提供された実装には、その機能を妨げるいくつかの問題があります。
元のコード:
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 }
実装のエラー:
複数のゴルーチンからの終了: n 変数は複数のゴルーチン間で共有され、更新されますチャネルの閉鎖を検出したときに各ゴルーチンによって実行されます。これにより、複数のゴルーチンが n に同時にアクセスして更新しようとすると、競合状態や予期しない動作が発生する可能性があります。
不正なチャネル キャプチャ: ループ内で作成された各ゴルーチンは、同じチャネル (最後のもの) をキャプチャします。これは、c にはゴルーチンに渡されるのではなく、反復ごとにチャネルの値が割り当てられるためです。 function.
解決された問題:
これらの問題に対処するために、変更されたコードではより安全な手法が採用されています:
WaitGroup の使用: sync.WaitGroup はゴルーチンの完了を追跡するために使用されます。各ゴルーチンはデータのポンピングが完了すると WaitGroup に信号を送り、メインのゴルーチンは出力チャネルを閉じる前にすべてのゴルーチンが完了するのを待ちます。
正しいチャネル キャプチャ: 各ゴルーチンはチャネルに渡されます。ラムダ関数内でリッスンし、各ゴルーチンが割り当てられたものを正しく監視していることを確認する必要があります。 channel.
改善された出力: 変更されたコードは、すべてのチャネルが均等な分布で出力チャネルに寄与する、期待どおりの出力を生成します。元の出力で観察されたシーケンシャル フィードは削除されます。
追加の考慮事項:
以上が競合状態やデータ損失を避けるために複数の Go チャネルを正しく多重化するにはどうすればよいでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。