1

次のコードサンプルでは、​​最新の値が確実に読み取られるようにするために、 FuncAのメモリバリアが必要ですか?

class Foo
{
   DateTime m_bar;

   void FuncA() // invoked by thread X
   {
      Thread.MemoryBarrier(); // is required?
      Console.WriteLine(m_bar);
   }

   void FuncB() // invoked by thread Y
   {
       m_bar = DateTime.Now;
   }       
}

編集:そうでない場合、FuncAが最新の値を読み取るようにするにはどうすればよいですか?(最近の値が実際にプロセッサのキャッシュに保存されていることを確認したい)[ロックを使用せずに]

4

5 に答える 5

2

私には大きな「いいえ」のように見えます。Thread.MemoryBarrier()は、それを実装したスレッド内のメモリアクセスのみを同期します。

MSDNから:

現在のスレッドを実行しているプロセッサは、MemoryBarrierの呼び出しに続くメモリアクセスの後にMemoryBarrierの呼び出しの前にメモリアクセスが実行されるように、命令を並べ替えることはできません。

于 2009-11-13T19:56:52.973 に答える
2

Datetime をティック数として保存することをお勧めします (タイプは「long」、つまり Int64 です)。ティック (新しい DateTime (ティック)) からティック (myDateTime.Ticks) に簡単に変換できます。次に、Interlocked.Read を使用して値を読み取り、Interlocked.Exchange を使用して高速な非ロック操作で値を書き込むことができます。

于 2009-11-13T20:09:49.180 に答える
1

はい、最新の値を取得できるようにメモリバリアが必要です。

メモリ バリアが存在しない場合、スレッド X が自身のキャッシュ ラインから m_bar の値を読み取る可能性がありますが、その値はメイン メモリに書き戻されていません (変更はスレッド Y に対してローカルに行われています)。変数を volatile として宣言することで、同じ効果を得ることができます。

volatile 修飾子は、通常、lock ステートメントを使用してアクセスをシリアル化せずに、複数のスレッドによってアクセスされるフィールドに使用されます。volatile 修飾子を使用すると、あるスレッドが別のスレッドによって書き込まれた最新の値を確実に取得できます。

この問題に関する良いエントリー (おそらく最高のもの) は、Joe Duffy による次のエントリーです:揮発性の読み取りと書き込み、および適時性

于 2009-11-13T20:10:26.193 に答える
0

メモリバリアは、実際にはワットロックと同じことを行います。フィールドがロックに入るときにメモリから最新の値を取得し、ロックを出る前にメモリに書き込まれることを保証します。
フィールドの値が常にメモリに対して読み取りまたは書き込みされ、最初にCPUのキャッシュに対して読み取りまたは書き込みによって最適化されないようにすることも、volatileキーワードを使用して実現できます。
プリミティブ整数型と参照型を除いて、DateTimeはCPUレジスタにキャッシュできないため、volatileキーワードで宣言する必要はありません(できません)。

于 2009-11-13T23:21:24.537 に答える
-1

32ビットアーキテクチャでは、このような状況で破損した読み取りが発生する可能性があるため、これは実際には問題ではありません

于 2009-11-14T20:48:31.153 に答える