プログラム内で、main 関数の外部で定義された関数で sync.WaitGroup を使用すると、問題が発生する可能性があります。この状況を調べてみましょう。
問題:
次のコードを考えてみましょう:
<code class="go">package main import ( "fmt" "sync" ) func main() { ch := make(chan int) var wg sync.WaitGroup wg.Add(2) go Print(ch, wg) // go func(){ for i := 1; i <= 11; i++ { ch <- i } close(ch) defer wg.Done() }() wg.Wait() //deadlock here } // Print prints all numbers sent on the channel. // The function returns when the channel is closed. func Print(ch <-chan int, wg sync.WaitGroup) { for n := range ch { // reads from channel until it's closed fmt.Println(n) } defer wg.Done() }</code>
ここでは、プログラムが数値を出力することを目的としています。 1 ~ 11 ですが、場合によっては 1 ~ 10 しか出力されません。
エラー分析:
sync.WaitGroup のコピーを Print 関数に渡しています。これは、メイン関数で待機している sync.WaitGroup の Done() メソッドを呼び出さないことを意味します。
解決策:
この問題を解決するには
<code class="go">package main import ( "fmt" "sync" ) func main() { ch := make(chan int) var wg sync.WaitGroup wg.Add(2) go Print(ch, &wg) go func() { for i := 1; i <= 11; i++ { ch <- i } close(ch) defer wg.Done() }() wg.Wait() //deadlock here } func Print(ch <-chan int, wg *sync.WaitGroup) { for n := range ch { // reads from channel until it's closed fmt.Println(n) } defer wg.Done() }</code>
これにより、Print 関数が main 関数で待機しているのと同じ sync.WaitGroup の Done() メソッドを呼び出すようになります。
あるいは、コードを再構築して、Print 関数の sync.WaitGroup への依存を削除することもできます。
<code class="go">package main import ( "fmt" ) func main() { ch := make(chan int) go func() { for i := 1; i <= 11; i++ { ch <- i } close(ch) }() for n := range ch { // reads from channel until it's closed fmt.Println(n) } }</code>
以上が外部関数で sync.WaitGroup を使用するとデッドロックが発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。