ホームページ > バックエンド開発 > Golang > Go で WaitGroups とバッファリングされたチャネルを使用すると、どのようにしてデッドロックが発生するのでしょうか?

Go で WaitGroups とバッファリングされたチャネルを使用すると、どのようにしてデッドロックが発生するのでしょうか?

Linda Hamilton
リリース: 2024-10-28 04:16:30
オリジナル
715 人が閲覧しました

How Can Deadlock Occur When Using WaitGroups and Buffered Channels in Go?

WaitGroups を使用した Go 同時実行におけるデッドロックの検出

Go では、ゴルーチンを調整するためにチャネルと待機グループを使用して同時実行を管理することがよくあります。ただし、デッドロックにつながる可能性がある潜在的な落とし穴を理解することが重要です。

問題の説明

バッファーされたチャネルと待機グループを使用しようとする次のコードを考えてみましょう。

<code class="go">package main

import (
    "fmt"
    "sync"
)

func main() {
    ch := make(chan []int, 4)
    var m []int

    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            ch <- m // Send to channel
            return
        }()
    }
    wg.Wait() // Wait for all goroutines to complete

    for c := range ch {
        fmt.Printf("c is %v", c) // Iterate over channel
    }
}</code>
ログイン後にコピー

容量に達するとチャネルが自動的に閉じることが期待されていたにもかかわらず、このコードは予期せずデッドロック エラーを引き起こします。

解決策

は 2 つあります。デッドロックにつながる主な問題:

  1. 不十分なチャネル容量: チャネル バッファーの容量は 4 ですが、それに書き込もうとするゴルーチンが 5 つあります。これにより、チャネルがいっぱいであるために書き込みを待機しているゴルーチンがブロックされる状況が発生します。
  2. 閉じられていないチャネル上の範囲: c := range ch のループは、チャネルからの受信要素をリッスンし続けます。チャネルを無期限に停止し、チャネルが閉じられるまで待機します。ただし、チャネルに書き込むゴルーチンが残っていないため、チャネルが閉じることはありません。

デッドロックを解決するには、次の 2 つの解決策があります。

解決策 1: チャネル容量の拡張と明示的なクローズ

<code class="go">ch := make(chan []int, 5) // Increase channel capacity
...
wg.Wait()
close(ch) // Close the channel to stop range loop</code>
ログイン後にコピー

これにより、チャネル内に十分なスペースがあることが保証され、明示的にクローズされ、範囲ループが終了できるようになります。

解決策 2: ゴルーチンで完了条件を通知する

<code class="go">func main() {
    ch := make(chan []int, 4)
    var m []int

    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            ch <- m
            wg.Done() // Signal completion within goroutine
            return
        }()
    }
    go func() {
        for c := range ch {
            fmt.Printf("c is %v\n", c)
            wg.Done() //Decrement count for each iteration
        }
    }()
    wg.Wait()
}</code>
ログイン後にコピー

この解決策では、各ゴルーチンは、ゴルーチン自体内で wg.Done() を呼び出すことによって、その完了を通知します。 waitgroup も反復ごとに range ループ内でデクリメントされ、wg.Wait() が最終的に完了してプログラムが終了することが保証されます。

以上がGo で WaitGroups とバッファリングされたチャネルを使用すると、どのようにしてデッドロックが発生するのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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