これは 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 サイトの他の関連記事を参照してください。