2009-07-05 4 views
18

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

シンプルで読み、適切に整列された32ビットの変数はアトミック操作

ですが追加に書き込みます:

をしかし、アクセスが保証されてはいない

MSDN says同期させる。ただし、アクセスの同期は保証されていません。 2つのスレッドが同じ変数から読み書きしている場合、一方のスレッドが他方のスレッドの書き込み操作を実行する前に、他方のスレッドが読み出し操作を実行するかどうかを判断することはできません。意味

、私はそれを理解し、他の一方で、変数の簡単な読み出し動作が行われることができることを、たとえば、InterlockedAdd操作が整備されています。では、なぜ変数を読み込む連動関数がないのですか?

私は値がInterlockedAdding ingゼロとして読めると思うが、それは正しい方法ではないようだ。

答えて

7

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

興味深いことに、.NETのInterlockedクラスは、.NET 2.0まではReadメソッドを取得しませんでした。私はInterlocked.ReadInterlocked.CompareExchangeを使って実装されていると信じています。 (Interlocked.Readのドキュメントでは、私は多少の誤解を招くことに注意してください - それは原子性について語りますが、ボラティリティではなく、.NETで非常に固有の意味です。

+0

ボラティリティの場合、Thread.VolatileReadファミリがあります。 –

+0

@JS:InterlockedCompareExchange64にアドバイスした特別な理由はありますか(64に重点を置いて)? Interlocked.Readは64ビット値でも動作し、32ビットマシンで32ビット値を読み取るときにはInterlockedCompareExchnage(32ビットバージョン)が不要であることを意味する "64ビットシステムではReadメソッドは不要"と言います。 –

+0

@Remus:Thread.VolatileReadについての良い点ですが、ドキュメンテーションでは、(あなたが意味するだろうThread.VolatileReadを指すのではなく)*心配する必要はありません。 @原因:64ビットバージョンを選択する特別な理由はありません。私は、ここで十分な微妙さがあると思うので、何もせずに逃げようとするときに必要なことを正確に主張したくないと思う。 –

7

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

+0

私の懸念が完全に愚かではないと聞いてうれしいです:) –

+0

@zvrba:私は同期化したもの(実際には、MSDNが同期化したもの)はあなたが並べ替えを呼び出すものだと思います。とにかく、私は本当にここの結論が何であるかは分かりません。これは答えかコメントか? –

+1

これは、回答がインターロックされた読み込みです(必要なことはありません)。 – zvrba

2

この全体の議論の核心部で、XXXのパーティションIにdevinedされる適切な位置合わせ、ある「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クラス操作の使用を介してのいずれか)

要約必要とされるかもしれません。あなたがしていることは、読んで特別な指示を必要としない可能性が非常に高いです...あなたが何をしているのかによって、注意する必要がある他のものがあるかもしれません。

+0

'volatile 'はレジスタに以前の値を保存するような"コンパイラ生成の "キャッシュに対してのみ保護するのではないでしょうか?つまり、「揮発性」はCPUキャッシュのために失効したデータを生成し、「連動」読み取りを使用すると後者に対して保護します。 –