同時実行ゴルーチンがシェア変数をインクリメントしているときに、Go プログラムの出力が常に 1 になるのはなぜですか?

Susan Sarandon
リリース: 2024-10-31 01:36:29
オリジナル
547 人が閲覧しました

Why is the output of my Go program always 1 when a concurrent goroutine is incrementing a shared variable?

これは Go コンパイラーがコードを最適化したためですか?

提供された Go コードでは、変数 i がメインの goroutine と goroutine の間で共有されています。 go func() { ... }() を使用して作成された同時実行ゴルーチン。並行ゴルーチンの目的は、i を無限にインクリメントすることです。ただし、プログラムを実行すると、同時実行ゴルーチンには i を何度もインクリメントする十分な時間があるため、はるかに大きな数値が期待されていたにもかかわらず、出力が常に 1 であることがわかりました。

この動作を理解するには、以下を行う必要があります。 Go メモリ モデルとコンパイラの最適化を考慮してください。

Go メモリ モデル

Go メモリ モデルは、1 つのゴルーチン内の変数の読み取りが保証される条件を指定します。別のゴルーチンの同じ変数への書き込みによって生成された値を観察します。

Go メモリ モデルによると、共有変数への変更がゴルーチン間で表示されるようにするには、その変更の後に次のような同期イベントが続く必要があります。チャネル操作またはミューテックスのロック。

コンパイラの最適化

この例では、同時ゴルーチン内での i への代入の後に同期イベントは発生しません。その結果、割り当てがメインの goroutine によって監視されることは保証されず、コンパイラは必要に応じてコードを自由に最適化できます。

アグレッシブなコンパイラは、インクリメント操作を完全に排除することでコードを最適化する可能性があります。 、並行ゴルーチンを効果的に削減して、何も行わない無限ループにします。この最適化により、メインの goroutine が同時実行 goroutine によって実行される増分を決して監視しないため、出力が常に 1 になる理由が説明されます。

共有変数への更新が goroutine 全体に正しく伝播されるようにするには、アクセスを同期することが重要です。チャネル、ミューテックス、または Go の sync および sync/atomic パッケージによって提供されるその他の同期プリミティブを使用して、これらの変数にアクセスします。

以上が同時実行ゴルーチンがシェア変数をインクリメントしているときに、Go プログラムの出力が常に 1 になるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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