ホームページ > バックエンド開発 > Golang > Go でスライスを使用しているにもかかわらず、ゴルーチンがすべて同じ値を出力するのはなぜですか?

Go でスライスを使用しているにもかかわらず、ゴルーチンがすべて同じ値を出力するのはなぜですか?

Susan Sarandon
リリース: 2024-12-20 02:40:10
オリジナル
807 人が閲覧しました

Why Do My Goroutines All Print the Same Value Despite Using a Slice in Go?

データ競合におけるゴルーチンの動作を理解する

提供されたコード スニペットは、Go における古典的なデータ競合の問題を示しています。目的はフィールドのリストから異なる値 (「one」、「two」、「three」) を出力することですが、実際の結果では「three」が 3 回出力されます。

これを解決するにはこの問題を解決するには、データ競合が発生する理由と場所を理解する必要があります。

データ競合の特定

問題は、 goroutine関数の引数の評価。ループがデータ スライスを反復処理するとき、範囲変数 v がループ本体に割り当てられ、v.print() の呼び出しで使用されます。ただし、 v 変数は要素のコピーであり、スライスは反復中に変更されるため、最終的にはすべてのゴルーチンがスライスの同じ最後の要素を指すことになります。

これは、ゴルーチンが実行されるときに、これらはすべて、意図した一意の値 (「one」、「two」、「three」) ではなく、最後の値 (「three」) を出力します。

可能解決策

この問題に対処してデータ競合を解消するには、いくつかの方法があります:

  1. ループ内に新しい変数を作成します:

    • v := を使用してループ内で新しい変数 v を宣言します。 v 構文では、各ゴルーチンがデータの独自のコピーで動作することを確認します。
  2. ポインターのスライスを使用します:

    • 元のスライスを渡す代わりに、ポインタのスライスを使用できます (例: []*分野)。ゴルーチンに渡されると、各ポインターはスライス内の一意の要素を指し、データ競合を回避します。
  3. スライス要素のアドレスを渡します:

    • あるいは、各スライス要素のアドレスを明示的に&data[i] 構文を使用する goroutine。これにより、各ゴルーチンが目的の要素への一意のポインタを持つことが保証されます。
  4. 引数を持つ匿名関数の使用:

    • ゴルーチン関数が匿名関数内にある場合、範囲変数を引数として匿名関数に渡し、分離することができます。ゴルーチンのデータへのアクセス。

これらのソリューションのいずれかを適用することで、データ競合を排除し、ゴルーチンが意図した一意の値 ("one"、 「2」、「3」) 順序は任意です。

以上がGo でスライスを使用しているにもかかわらず、ゴルーチンがすべて同じ値を出力するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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