Go でのチャネルでのタイムアウトの使用
Goroutine とチャネルは、Go での同時プログラミングのための強力なメカニズムを提供します。ただし、ゴルーチンでのタイムアウトの処理は難しい場合があります。
ゴルーチンとタイムアウトを使用して URL リストの到達可能性を確認するシナリオでは、タイムアウトが実行されない状況が発生する可能性があります。一部の URL は到達できません。
提供されたコードを分析してみましょう:
func check(u string) bool { time.Sleep(4 * time.Second) return true } func IsReachable(urls []string) bool { ch := make(chan bool, 1) for _, url := range urls { go func(u string) { select { case ch <- check(u): case <-time.After(time.Second): ch <- false } }(url) } return <-ch }
問題はチェック関数内にあります。 goroutine で time.Sleep を使用すると、現在の goroutine (この場合は check 関数を実行している goroutine) が一時停止されます。チェック関数が一時停止している間、外側のゴルーチン内の select ステートメントは引き続き実行を試みます。
この場合、select ステートメントの両方のブランチ (結果またはタイムアウトのチェック) は 4 の後に実行可能になります。チェックが戻ったときの秒数。ただし、両方のブランチが実行可能であるため、ランタイムはどちらかを実行することを選択でき、その結果常に true が返される可能性があります。
これを解決するには、次に示すように、チェック関数ごとに新しい goroutine を作成する必要があります。以下の修正されたコード:
func check(u string, checked chan<- bool) { time.Sleep(4 * time.Second) checked <- true } func IsReachable(urls []string) bool { ch := make(chan bool, 1) for _, url := range urls { go func(u string) { checked := make(chan bool) go check(u, checked) select { case ret := <-checked: ch <- ret case <-time.After(time.Second): ch <- false } }(url) } return <-ch }
この場合、チェック関数は別の goroutine で実行され、外部の goroutine が一時停止されず、タイムアウトが正しく実行されることが保証されます。
以上がチャネルを使用した Go ゴルーチンでタイムアウトを正しく実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。