WaitGroups と Buffered Channels を使用した Go コードでデッドロックが発生する原因は何ですか?

PHPz
リリース: 2024-02-09 11:09:30
転載
752 人が閲覧しました

使用 WaitGroups 和 Buffered Channels 的 Go 代码中出现死锁的原因是什么?

#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)
}
ログイン後にコピー

Solution

main 関数のコードは連続的です。

最初に 3k 値を inputchan then## に書き込んでみてください。 #値は outputchan から読み取られます。 コードは最初のステップでブロックされます:

3,000 個の値が
    inputchan
  • に正常に送信されるまで、outputchan から何も排出されないため、ワーカーは最初の 1,000 個の値の後、outputchan &lt でスタックしてしまいます ;-私###### ワーカーが inputchan からのリソースの消費を停止すると、
  • main
  • は約 2,000 個の値の後に inputchan <- i でスタックします。 この問題を解決する 1 つの方法は、プロデューサー (inputchan <- i
  • ) と最終コンシューマー (
for o := range Outputchan {

) を別の goroutines に含めることです。手術。 これらのアクターの 1 つをメインの goroutine に保持し、もう 1 つに対して新しいアクターをスピンアップすることができます。例えば:### リーリー https://www.php.cn/link/80e4c54699b5b8cf8c67dd496909fceb

追加の注意:

done のシグナリングに関する操作の順序は重要です。チャネル done

outputchanwg.done でのみ使用できます。 () すべての作業者に、終了したら閉じるように指示します。 リーリー

以上がWaitGroups と Buffered Channels を使用した Go コードでデッドロックが発生する原因は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:stackoverflow.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート