ホームページ >バックエンド開発 >Golang >シングルスレッドの Go プログラムで Goroutine 出力をインターリーブするのに「runtime.Gosched()」が重要なのはなぜですか?

シングルスレッドの Go プログラムで Goroutine 出力をインターリーブするのに「runtime.Gosched()」が重要なのはなぜですか?

DDD
DDDオリジナル
2024-12-21 12:30:10225ブラウズ

Why is `runtime.Gosched()` Crucial for Interleaving Goroutine Output in Single-Threaded Go Programs?

出力のインターリーブに Runtime.Gosched() が必要なのはなぜですか?

Go の以前のバージョンでは、runtime.Gosched() が使用されていた場合、以下のコードは予期しない動作を示しました。削除されました:

package main

import (
    "fmt"
    "runtime"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        runtime.Gosched()
        fmt.Println(s)
    }
}

func main() {
    go say("world")
    say("hello")
}

で出力runtime.Gosched():

hello
world
hello
world
hello
world
hello
world
hello

runtime.Gosched() を使用しない出力:

hello
hello
hello
hello
hello

runtime.Gosched() の役割を理解する

GOMAXPROCS 環境変数を指定せずに Go を実行すると、すべてgoroutine は、単一の OS スレッドで実行されるようにスケジュールされます。プログラムをマルチスレッドとして見せるには、Go スケジューラーは実行コンテキストを時々切り替える必要があります。

協調マルチタスク:

Go は協調マルチタスク モデルを使用します。つまり、ゴルーチンは明示的に制御を譲る必要があります。他のゴルーチンに。これは、スケジューラが実行コンテキストを透過的に切り替える OS スレッドのプリエンプティブ マルチタスクとは対照的です。

runtime.Gosched() の関数:

プリエンプティブ マルチタスクがない場合, runtime.Gosched() を使用すると、ゴルーチンが制御をスケジューラーに渡すことができます。 goroutine が Gosched 呼び出しに到達すると、スケジューラは別の goroutine に実行を切り替えるように指示します。

上記の例では、Gosched を削除するということは、実行コンテキストがメイン ルーチンから離れることがないことを意味します。その結果、「world」ゴルーチンの実行は決して許可されず、「world」メッセージは出力されません。

GOMAXPROCS: スレッド数の指定

GOMAXPROCS を正の数に設定 (例: runtime.GOMAXPROCS(2)) により、Go はその数までネイティブ スレッドを作成できます。 GOMAXPROCS が 1 より大きい場合、ゴルーチンを別のスレッドで実行するようにスケジュールでき、真の並列処理が可能になります。

GOMAXPROCS を 2 以上に設定すると、ランタイムがなくても、例のゴルーチンはインターリーブされます。Gosched ()、プリエンプティブ マルチタスクを示します。

以上がシングルスレッドの Go プログラムで Goroutine 出力をインターリーブするのに「runtime.Gosched()」が重要なのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。