ホームページ  >  記事  >  バックエンド開発  >  WaitGroup とバッファーが制限されているチャネルを使用する場合、Go でデッドロックを回避するにはどうすればよいですか?

WaitGroup とバッファーが制限されているチャネルを使用する場合、Go でデッドロックを回避するにはどうすればよいですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-10-27 01:21:02959ブラウズ

How can you avoid deadlock in Go when using WaitGroup and a channel with a limited buffer?

WaitGroup と Channel を使用した Go のデッドロック

Go では、2 つ以上のゴルーチンが他方のゴルーチンの終了を無期限に待機すると、デッドロックが発生します。この例では、チャネル バッファーの不足と、WaitGroup を使用したゴルーチンの不適切な同期によって引き起こされるデッドロックの問題を調べます。

コード

<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 つの値を送信しようとします。ただし、チャネルがいっぱいになると、受信者が使用可能になるまでブロックされます。送信中のすべてのゴルーチンが終了したため、チャネルから受信できるゴルーチンはありません。

さらに、チャネル上に範囲を設定するゴルーチン (c := range ch の場合) も、より多くの値を期待しているため、無期限にブロックされたままになります。それ以上送信されていないにもかかわらずチャネルに到着すること。これにより、送信者と受信者の両方がお互いを待機するデッドロックが発生します。

解決策 1: チャネル バッファーを増やして閉じる

デッドロックを回避する 1 つの解決策は、次のとおりです。チャネル バッファ サイズを送信ゴルーチンの数以上の値に増やします。さらに、すべての送信が完了した後、チャネルを閉じる必要があります。これは、これ以上値を受信しないことを示します。

<code class="go">ch := make(chan []int, 5)
...
wg.Wait()
close(ch)</code>

解決策 2: Goroutine の受信で Done() を実行する

もう 1 つの解決策は、main 関数ではなく受信ゴルーチンで Done() を実行することです。そうすることで、値がゴルーチンによって受信されて消費されるまで、WaitGroup はデクリメントされません:

<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
            return
        }()
    }
    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 までご連絡ください。