ホームページ  >  記事  >  バックエンド開発  >  WaitGroup とバッファリングされたチャネルを使用して提供された Go コードでデッドロックが発生するのはなぜですか?

WaitGroup とバッファリングされたチャネルを使用して提供された Go コードでデッドロックが発生するのはなぜですか?

Barbara Streisand
Barbara Streisandオリジナル
2024-10-26 22:08:02680ブラウズ

Why does the provided Go code with WaitGroup and buffered channel result in a deadlock?

WaitGroup とバッファリングされたチャネルによる Go のデッドロック

Go では、複数の goroutine が互いの完了を待っているときにデッドロックが発生します。膠着状態にある。この状況は、バッファリングされたチャネルと WaitGroups を誤って使用すると発生する可能性があります。

次のコードを考えてみましょう:

<code class="go">package main

import "fmt"
import "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
            return
        }()
    }
    wg.Wait()

    for c := range ch {
        fmt.Printf("c is %v", c)
    }
}</code>

このコードは、バッファ サイズ 4 のチャネルを作成し、5 つのゴルーチンを開始することが想定されています。 、それぞれが空のスライスをチャネルに送信します。メインの goroutine は、すべての goroutine が終了するのを待ってから、チャネル上で範囲を広げます。

ただし、このコードではデッドロックが発生します。なぜですか?

デッドロックの原因:

コードには 2 つの問題があります:

  1. チャネル容量: チャネルの容量は次のとおりです。 4 は、最大 4 つの要素を保持できることを意味します。ただし、チャネルに送信しようとしているゴルーチンが 5 つあるため、最後のゴルーチンがスロットが解放されるのを待ってブロックされる状況が発生します。
  2. チャネルを閉じる: range ch ループは要素を待機し続けます。チャンネルに入ります。チャネルに書き込むゴルーチンがもう残っていないため、ループは無期限に待機します。

解決策:

  1. チャネル容量を増やす: チャネル容量を 5 に増やすと、すべてのゴルーチンがブロックせずに値を送信するのに十分なスロットが利用可能になります。さらに、ゴルーチンの書き込みが終了した後にチャネルを閉じると、これ以上要素が来ないことが範囲ループに通知され、無限に待機することがなくなります。

    <code class="go">ch := make(chan []int, 5)
    ...
    wg.Wait()
    close(ch)</code>
  2. Use Done () ループ内: チャネルを閉じる代わりに、WaitGroup の Done() メソッドを使用して、最後のゴルーチンが終了したことを知らせることができます。範囲ループ内で Done() を呼び出すことで、チャネルが空になったときにメインの goroutine に通知され、ループを終了できます。

    <code class="go">go func() {
        for c := range ch {
            fmt.Printf("c is %v\n", c)
            wg.Done()
        }
    }()
    wg.Wait()</code>

これらのソリューションは、次のことを保証することでデッドロックを解決します。チャネルに十分な容量があり、チャネルから読み取る要素がなくなったときに範囲ループが終了すること。

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

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。