Go コードが単に「最初のメッセージを表示: hello」ではなく、100 億の数値の合計を出力するのはなぜですか?

DDD
リリース: 2024-10-28 07:49:02
オリジナル
145 人が閲覧しました

Why does my Go code print the sum of 10 billion numbers instead of just

Go の同時実行性とチャネルの混乱

問題

ユーザーは Go の同時実行性を理解しようとしています

<code class="go">package main

import "fmt"

func display(msg string, c chan bool) {
    fmt.Println("display first message:", msg)
    c <- true
}

func sum(c chan bool) {
    sum := 0
    for i := 0; i < 10000000000; i++ {
        sum++
    }
    fmt.Println(sum)
    c <- true
}

func main() {
    c := make(chan bool)

    go display("hello", c)
    go sum(c)
    <-c
}</code>
ログイン後にコピー

メイン関数はチャネルからデータを受信したら終了する必要があるため、期待される出力は「最初のメッセージの表示: hello」のみです。ただし、実際の出力には 100 億個の数値の合計も含まれます。

Answer

コードの主な問題は、スケジューラが 2 つのゴルーチンの間で自由に選択できることです。 (表示と合計) ブロックされていません。プログラマは、表示が最初に終了し、合計が完了する前にチャネルにデータが送信されることを期待していますが、スケジューラの非決定的な性質により、これが起こらない可能性があります。

考えられる 1 つの実行シナリオ:

  1. main は、表示と合計のための 2 つのゴルーチンを作成します。
  2. スケジューラはすぐに表示に切り替わります。
  3. ディスプレイはメッセージを出力し、受信側がチャネルに送信されたデータを受け入れるのをブロックします。 .
  4. スケジューラは表示を再開する代わりに sum を実行します。
  5. sum は 100 億個の数値の合計を計算して出力します。
  6. スケジューラは sum の終了後に表示を再開することを選択します。
  7. ディスプレイはチャネルにデータを送信します。
  8. スケジューラはメインに切り替えてチャネルからデータを受信します。
  9. メインは合計を出力し、プログラムを終了します。

この問題に対処し、「ディスプレイの最初のメッセージ: hello」メッセージが排他的に出力されるようにするための 1 つの方法は、結果チャネルを使用してディスプレイからメッセージを受信し、プログラムを直ちに終了することです。変更された main 関数は次のようになります:

<code class="go">func main() {
    result := make(chan string)

    go display("hello", result)
    fmt.Println(<-result)
}</code>
ログイン後にコピー

以上がGo コードが単に「最初のメッセージを表示: hello」ではなく、100 億の数値の合計を出力するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!