ホームページ > バックエンド開発 > Golang > Go ルーチンのデータ競合で、Go コードが「One」、「Two」、「Three」ではなく「Three」を 3 回出力するのはなぜですか?

Go ルーチンのデータ競合で、Go コードが「One」、「Two」、「Three」ではなく「Three」を 3 回出力するのはなぜですか?

Linda Hamilton
リリース: 2024-12-07 22:23:13
オリジナル
908 人が閲覧しました

Why Does My Go Code Print

データ競合シナリオにおけるゴルーチンの奇妙な動作を理解する

提供された Go コードでは、data と呼ばれる構造体フィールドのスライスを作成します。 「one」、「two」、「three」という名前が含まれています。コードはスライスを反復処理し、print メソッドを使用して各フィールドの名前を出力するゴルーチンを作成します。ただし、予想に反して、コードは意図した "one"、"two"、"three" の順序ではなく、"three" を 3 回繰り返し出力します。

データ競合の解明

この奇妙な動作は、複数のゴルーチンが同じ共有データに同時にアクセスし、変更する可能性があるときに発生するデータ競合に起因します。この場合、ゴルーチンの作成時に範囲変数 v のアドレスが暗黙的に使用されるために問題が発生します。ループ変数 v が各反復で変更されると、ゴルーチンは最終値を使用することになり、その結果、常に「three」が出力されます。

データ競合への対処

この問題を解決するには、いくつかの方法を採用できます。アプローチ:

  • 各ループ反復での新しい変数の作成: ループ内で、範囲変数と同じ名前の新しい変数を宣言し、効果的に変数を作成できます。の新しいスコープvariable.

  • ポインターのスライスの使用: 構造体フィールドのスライスを使用する代わりに、フィールドへのポインターのスライスを使用できます。これにより、ゴルーチンが個々のフィールド要素へのポインタを確実に受け取り、データ競合の問題を防ぐことができます。

  • スライス要素のアドレスを渡す: 別の代替方法は、次のとおりです。スライス内の各要素のアドレスをgoroutine.

  • 匿名関数の使用と引数として範囲変数の受け渡し: goroutine 関数が匿名関数内にある場合、次のように渡すことで問題を回避できます。への引数としての範囲変数function.

これらのアプローチにより、ゴルーチンが必要なデータの独自のコピーを確実に保持し、データ競合が排除され、「one」、「two、」の正しい出力が生成されます。 「」と「3」は順不同です。

以上がGo ルーチンのデータ競合で、Go コードが「One」、「Two」、「Three」ではなく「Three」を 3 回出力するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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