ホームページ > バックエンド開発 > Golang > 無限ループを持つゴルーチンは Go で他のゴルーチンをブロックするにはどうすればよいでしょうか?

無限ループを持つゴルーチンは Go で他のゴルーチンをブロックするにはどうすればよいでしょうか?

DDD
リリース: 2024-12-04 22:33:14
オリジナル
779 人が閲覧しました

How Can a Goroutine with an Infinite Loop Block Other Goroutines in Go?

他のゴルーチンをブロックする

Go では、ゴルーチンは軽量の実行スレッドです。通常、ゴルーチンは互いにブロックすることなく同時に実行できます。ただし、特定の状況下では、1 つのゴルーチンが他のゴルーチンの実行をブロックする可能性があります。

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

func main() {
    timeout := make(chan int)
    go func() {
        time.Sleep(time.Second)
        timeout <- 1
    }()

    res := make(chan int)
    go func() {
        for {
        }
        res <- 1
    }()
    select {
    case <-timeout:
        fmt.Println("timeout")
    case <-res:
        fmt.Println("res")
    }
}
ログイン後にコピー

この例では、ゴルーチンは無限ループで開始されます。通常、このゴルーチンは他のゴルーチンの実行を妨げるべきではありません。ただし、最初のゴルーチンが何らかの理由で 2 番目のゴルーチンのタイムアウト チャネルへの送信をブロックしているようです。

説明

この動作は、ゴルーチンの仕組みによるものです。 Goで予定されています。協調スケジューリングが使用されます。これは、別の goroutine を実行するには、goroutine が自発的にスケジューラに実行を渡す必要があることを意味します。提供されたコードでは、無限ループのあるゴルーチンは決して譲歩せず、他のゴルーチンの進行を妨げます。

ゴルーチンは通常、次の条件下で譲歩します:

  • バッファリングされていないチャネル送信/receive
  • システムコール (例: ファイル/ネットワーク)読み取り/書き込み)
  • メモリ割り当て
  • Time.Sleep() が呼び出されます
  • runtime.Gosched() が呼び出されます

この場合、これらの条件がどれも満たされないため、無限ループを伴うゴルーチンは実行を継続します。

解決策

この問題を解決するには、いくつかの解決策が考えられます。

  • プリエンプティブ スケジューラを使用します。 これは進行中の作業ですが、これにより、ゴルーチンをいつでも中断できるようになります。
  • バッファなしのチャネルを使用します。 バッファなしのチャネルに送信すると、別のゴルーチンが受信できるようになるまで送信者はブロックされます。
  • timer. time.After() 関数を使用すると、指定された期間後に受信するチャネルを作成できます。このチャネルに送信することで、ゴルーチンを強制的に譲歩できます。
  • 無限ループ内で runtime.Gosched() を使用します。 これにより、明示的にスケジューラに実行が譲られます。

特定のアプリケーションに最適なソリューションは、ゴルーチンの性質と望ましい動作によって異なります。

以上が無限ループを持つゴルーチンは Go で他のゴルーチンをブロックするにはどうすればよいでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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