4

次のコードがあるとします。

class Program
 {
    static volatile bool flag1;
    static volatile bool flag2;
    static volatile int val;
    static void Main(string[] args)
    {
      for (int i = 0; i < 10000 * 10000; i++)
      {
        if (i % 500000 == 0)
        {
          Console.WriteLine("{0:#,0}",i);
        }

        flag1 = false;
        flag2 = false;
        val = 0;

        Parallel.Invoke(A1, A2);

        if (val == 0)
          throw new Exception(string.Format("{0:#,0}: {1}, {2}", i, flag1, flag2));
      }
    }

    static void A1()
    {
      flag2 = true;
      if (flag1)
        val = 1;
    }
    static void A2()
    {
      flag1 = true;
      if (flag2)
        val = 2;
    }
  }
}

せいだ!主な質問は、なぜ... CPU が flag1 = true; で操作を並べ替えると思います。および if(flag2) ステートメントですが、変数 flag1 および flag2 は揮発性フィールドとしてマークされています...

4

2 に答える 2

5

.NET メモリ モデルでは、ランタイム (CLI) により、volatile フィールドへの変更がレジスタにキャッシュされないことが保証されるため、任意のスレッドでの変更は、他のスレッドですぐに確認されます (:これは、Java のメモリ モデルを含む他のメモリ モデルには当てはまりません)。 )。

しかし、これは、揮発性であるかどうかにかかわらず、複数のフィールドにわたる操作の相対的な順序については何も言いません。

複数のフィールド間で一貫した順序を提供するには、ロック (またはメモリ バリアを含むメソッドの 1 つを使用して明示的または暗黙的にメモリ バリア) を使用する必要があります。

詳細については、「Windows での並行プログラミング」、Joe Duffy、AW、2008 年を参照してください。

于 2010-04-15T12:40:28.223 に答える