20

Win32 api には、単純な変数をアトミックかつ同期的に操作するための一連の InterlockedXXX 関数がありますが、単純に変数の値を取得するための InterlockedRead 関数はないようです。どうして?

MSDN は次のように述べています。

適切にアラインされた 32 ビット変数への単純な読み取りと書き込みは、アトミック操作です。

しかし、追加します:

ただし、アクセスが同期されるとは限りません。2 つのスレッドが同じ変数に対して読み取りと書き込みを行っている場合、一方のスレッドが読み取り操作を実行してから、もう一方のスレッドが書き込み操作を実行するかどうかを判断することはできません。

つまり、私が理解しているように、別の、たとえば InterlockedAdd 操作が行われている間に、変数の単純な読み取り操作が行われる可能性があることを意味します。では、変数を読み取るための連動関数がないのはなぜでしょうか?

InterlockedAdd-ing zero の結果として値を読み取ることができると思いますが、それは正しい方法ではないようです。

4

3 に答える 3

8

これを実装する通常の方法はInterlockedCompareExchange64、両方の値が同じである比較交換操作 (例: ) を使用することです。なんらかの理由で 0 を加算するよりも効率的に実行できるのではないかとこっそり疑っていますが、これを裏付ける証拠はありません。

興味深いことに、.NET のクラスには.NET 2.0 までメソッドInterlockedがありませんでした。を使用して実装されてReadいると思います。( のドキュメンテーションはやや誤解を招くように私を驚かせることに注意してください- それはアトミック性について語っていますが、揮発性については語っていません。これは、.NET に非常に固有のものを意味します。Win32 メモリ モデルが、別のメモリから新しく書き込まれた値の可視性について何を保証するのかわかりません。スレッド、もしあれば。)Interlocked.ReadInterlocked.CompareExchangeInterlocked.Read

于 2009-07-05T18:43:30.000 に答える
7

「同期していない」というあなたの解釈は間違っていると思います。単純な読み取りアトミックですが、並べ替えとメモリの可視性の問題を自分で処理する必要があります。前者は適切な場所でフェンス命令を使用して処理され、後者は読み取りの問題ではありません (ただし、潜在的な同時書き込みは適切な可視性を確保する必要があり、インターロック関数がLOCKED asm 命令にマップする場合はこれを行う必要があります)。

于 2009-07-05T20:10:42.257 に答える
2

この議論全体の核心は適切な配置であり、これはxxxのパーティションIのセクション' 12.6.2 Alignment'で定義されています。

Built-in datatypes shall be properly aligned, which is defined as follows:
• 1-byte, 2-byte, and 4-byte data is properly aligned when it is stored at
  a 1-byte, 2-byte, or 4-byte boundary, respectively.
• 8-byte data is properly aligned when it is stored on the same boundary
  required by the underlying hardware for atomic access to a native int.

基本的に、すべての32ビット値には必要な配置があり、64ビットプラットフォームでは、64ビット値にも必要な配置があります。

ただし、注意:メモリ内のクラスのレイアウトを明示的に変更する属性があります。これにより、この配置が失われる可能性があります。ただし、これらは特にこの目的のための属性であるため、レイアウトの変更に着手していない限り、これは当てはまりません。

それが邪魔にならないように、Interlockedクラスの目的は、(言い換えると)「前」または「後」の状態でのみ観察できる操作を提供することです。インターロックされた操作は、通常、メモリを変更する場合にのみ問題になります(通常、重要な比較交換タイプの方法で)。見つけたMSDNの記事が示すように、読み取り操作(適切に配置されている場合)は、それ以上の予防措置を講じることなく、常にアトミックと見なすことができます。

ただし、読み取り操作を処理する場合は、他にも考慮事項があります。

  • 最近のCPUでは、読み取りはアトミックである可能性がありますが、どこかの古いキャッシュから間違った値を返す可能性もあります...これは、期待する動作を得るためにフィールドを「揮発性」にする必要がある場合があります
  • 32ビットハードウェアで64ビット値を処理している場合は、64ビット値全体Interlocked.Readが単一のアトミック操作で読み取られることを保証するために操作を使用する必要がある場合があります(そうでない場合は、2つの別個の32ビットとして実行される場合があります)メモリ更新のいずれかの側からの読み取り)
  • 読み取り/書き込みの順序を変更すると、期待した値が得られない場合があります。その場合、何らかのメモリバリアが必要になる可能性があります(明示的またはInterlockedクラス操作の使用による)

短い要約; アトミック性に関する限り、あなたがしていることは、読むための特別な指示を必要としない可能性が非常に高いです...しかし、あなたがしていることによっては、注意しなければならないことが他にもあるかもしれません。

于 2009-07-06T01:57:44.870 に答える