ホームページ > バックエンド開発 > Golang > 「default」ケースを使用しないと Go の「select」ステートメントがハングするのはなぜですか?それを修正するにはどうすればよいですか?

「default」ケースを使用しないと Go の「select」ステートメントがハングするのはなぜですか?それを修正するにはどうすればよいですか?

Barbara Streisand
リリース: 2024-11-24 06:31:15
オリジナル
384 人が閲覧しました

Why Does a Go `select` Statement Hang Without a `default` Case and How Can It Be Fixed?

Select を使用したゴルーチンが fmt.Print() なしで停止しない

問題:

Go Tour 演習内#71、 go run 71_hang.go nogood を使用すると、 go run 中にプログラムが無期限に実行されます。 71_hang.go OK は期待どおりに動作します。唯一の違いは、select ステートメントのデフォルトのケースに fmt.Print("") が追加されていることです。

説明:

select ステートメントのデフォルトのステートメントが変更されます。ステートメントの動作。デフォルトを使用しない場合は、チャネルにメッセージが表示されるまでブロックを選択します。デフォルトでは、チャネルから読み取るものがなくなるたびに、select はデフォルトのステートメントを実行します。

元のコードでは、default ステートメントにより無限ループが作成されます。スケジューラは他のゴルーチンをスケジュールできないため、プログラムは無限に実行されます。

解決策 1:

デフォルトのステートメントを削除し、非ブロック選択を使用します:

for {
    select {
        case todo := <-toDoList:
            if todo.depth > 0 && !visited[todo.url] {
                crawling++
                visited[todo.url] = true
                go crawl(todo, fetcher, toDoList, doneCrawling)
            }
        case <-doneCrawling:
            crawling--
    }
    if crawling == 0 {
        break
    }
}
ログイン後にコピー

解決策2:

デフォルトのステートメントを保持しますが、ゴルーチンが必ず結果を返すようにします。これを実現する 1 つの方法は、GOMAXPROCS=2 を使用することです。これにより、スケジューラーが複数のコアを使用できるようになります。

追加の注意:

Goroutine は協調的にスケジュールされます。 Select は、ゴルーチンが譲歩すべきポイントです。ただし、指定された例で、fmt.Print() ステートメントがないと select が生成されない理由は完全には理解されていないため、さらなる調査が必要です。

以上が「default」ケースを使用しないと Go の「select」ステートメントがハングするのはなぜですか?それを修正するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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