#php エディター Baicao が、この記事でよくある質問に答えます。「WaitGroups と Buffered Channels を使用した Go コードでデッドロックが発生する理由は何ですか?」Go 言語、WaitGroups と Bufferedチャネルは、一般的に使用される同時プログラミング ツールです。ただし、それらを使用するコードでデッドロック状況が発生する場合があります。この記事では、デッドロックの原因を詳しく掘り下げ、読者がこの問題を回避できるようにする解決策を提供します。初心者でも経験豊富な Go 開発者でも、この記事は貴重な情報を提供します。
待機グループ、バッファチャネル、デッドロック
私のこのコードはデッドロックを引き起こしますが、理由はわかりません。いくつかの異なる場所でミューテックスを使用して、別々の go ルーチンの内側と外側のチャネルを閉じてみましたが、結果は同じでした。
あるチャネル (inputchan) を介してデータを送信し、別のチャネル (outputchan) からデータを読み取ろうとします。
package main import ( "fmt" "sync" ) func listStuff(wg *sync.WaitGroup, workerID int, inputChan chan int, outputChan chan int) { defer wg.Done() for i := range inputChan { fmt.Println("sending ", i) outputChan <- i } } func List(workers int) ([]int, error) { _output := make([]int, 0) inputChan := make(chan int, 1000) outputChan := make(chan int, 1000) var wg sync.WaitGroup wg.Add(workers) fmt.Printf("+++ Spinning up %v workers\n", workers) for i := 0; i < workers; i++ { go listStuff(&wg, i, inputChan, outputChan) } for i := 0; i < 3000; i++ { inputChan <- i } done := make(chan struct{}) go func() { close(done) close(inputChan) close(outputChan) wg.Wait() }() for o := range outputChan { fmt.Println("reading from channel...") _output = append(_output, o) } <-done fmt.Printf("+++ output len: %v\n", len(_output)) return _output, nil } func main() { List(5) }
最初に 3k 値を inputchan
then## に書き込んでみてください。 #値は outputchan から読み取られます。
コードは最初のステップでブロックされます:
3,000 個の値が
outputchan
から何も排出されないため、ワーカーは最初の 1,000 個の値の後、outputchan < でスタックしてしまいます ;-私######
ワーカーが inputchan
からのリソースの消費を停止すると、inputchan <- i
でスタックします。
この問題を解決する 1 つの方法は、プロデューサー (
inputchan <- i) を別の goroutines に含めることです。手術。
これらのアクターの 1 つをメインの goroutine に保持し、もう 1 つに対して新しいアクターをスピンアップすることができます。例えば:###
リーリー
https://www.php.cn/link/80e4c54699b5b8cf8c67dd496909fceb
追加の注意:
done のシグナリングに関する操作の順序は重要です。チャネル done
とoutputchan は
wg.done でのみ使用できます。 () すべての作業者に、終了したら閉じるように指示します。
リーリー
以上がWaitGroups と Buffered Channels を使用した Go コードでデッドロックが発生する原因は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。