混ぜて行う状況を考えてみましょう。他のスレッドと衝突することを考慮する必要がありません。ロックによって保護する必要があります。ロック境界において、ソースコードの順序とプログラム順序が一致することを保証します。コンパイラが命令列をインターリーブできれば、性能が上がる可能性があります。よる実行を続けることが出来ます。先程のものよりも高速に実行できる可能性があります。それから読み込んだ結果を使用します。それは実質的にタダで行うことができます。その間に計算してしまえるからです。操作がクリティカルセクション内で実行されるようになりました。これらが発生する正確なタイミングは問題にはなりません。移動することはまったく安全ではありません。「上方向に」解放バリアを超えて移動することが出来ます。この種の移動を行うことは出来ません。すべての書き込みが解放書き込みであると言うことが出来ます。読み込みを他の読み込みに対してお互い並べ替えることは出来ません。読み込みを他の読み込みの取得バリアを超えて「上方向に」移動することは出来ません。書き込みを他の書き込みに対してお互い並べ替えることは出来ません。書き込みを他の書き込みの解放バリアを超えて「下方向に」移動することは出来ないためです。読み込みの後の書き込みを並べ替えることは出来ません。どちらの命令もそのようなことは認めていません。いずれの命令も他方のバリアを超えてその方向に移動することが出来ます。おいては、書き込み/読み込みバリアだけが必要なわけです。コンパイラがどのようにコードを並べ替えることが許されるかということも含まれています。実践メモリ一貫性の問題をデバッグすることは非常に困難です。デバッガでメモリダンプを調査しても、原因を見つけることは出来ないでしょう。レジスタは「有り得ない」状態で表示されます。してはいけないことここでは間違ったコードの例をいくつか、簡単な修正方法と共に示します。その前に、基本的な言語機能の使い方について議論する必要があります。宣言は非常に便利です。場所へのアクセスを省略したり並び替えたりしません。読み書きが期待通りの順序で起きることが保証されます。ないアクセスは、並び替えられる可能性があります。(明示的なコンパイラ並び替えバリアが必要な場合があるということです)。組み込みのアトミック操作関数を用意することでこの問題に対応する方向に改訂されつつあります。それは代わりにアトミック操作を使うべきだという強いシグナルです。ここでは、実用的な状況での使い方を示すために、アトミック操作を使います。ここではコンパイラの最適化による効果は無視します。中にはシングルプロセッサでさえ正しく動作しないコードもあります。後者のみを論ずることにします。この時点で、他のスレッドからその値を見ることが出来るようになります。これは大丈夫なのでしょうか。危険な仮定を置いています)。書き込みがフィールドの初期化よりも前に見える可能性があります。5、0、または未初期化のデータを見る可能性すらあります。これは最後の代入を以下のように変更すれば修正できます。thing);これにより、他のすべてのスレッドに正しい順序で書き込みが見えるようになります。おいては、問題ありません。読み込みよりも後に見えることが保証されます。アーキテクチャの詳細に依存するのは得策ではありません。そのコードは非常に微妙なところで移植性が無いということになるからです。完全な修正としては、読み込みの後にもバリアが必要です。thing->x;これにより、正しい順序になりました。これではコードを書くのが面倒なように思えるかもしれません。支払わなければならないコストです。アドレス依存は常に役に立つわけではありません。読み書きはアウトオブオーダーで見えます。「ランダムな」未初期化データを読み込む可能性はありません。true);読み込みを以下のように変更する必要があります。atomic_acquire_load(&gGlobalThing.initialized);同じ問題のもうひとつの例は、参照カウントを使ったデータ構造の実装時に起きます。一貫性が保たれるでしょう。エッジケースではまだ問題が起きる可能性があります。参照カウントを減らします。操作であるため、正しく動きます。なり、記憶領域は回収されます。必要なものを取り出し、それから解放します。アトミック操作とアトミックでない操作が並べ替えられる可能性があります。読み込みが見える可能性があります。格納される可能性があります。他のスレッドが同じ場所に新しいオブジェクトを作成したとかです。置き換えることで修正できます。読み込みが見えることが保証されます。ほとんどの場合、上記の例は実際には失敗しません。おいては、上記のコードは失敗する可能性があります。言語機能については述べてきませんでした。それをざっと見ていきましょう。言語に用意されている組み込みのロック機構です。相互排他アクセスを行うために使うことが出来ます。ブロックの実装は、スピンロックの例と同じ基本的な構造を持っています。行い、最後に解放書き込みを行います。ブロックの中に移動できるということです。ひとつ重要なことがあります。それらがひとつのブロックに結合されてしまう可能性があります。それと同じくらい弱いものでした。モニタ同期のレベルに近い強い保証が得られるようになりました。アクセスの効果は例を用いて示すことが出来ます。よってそれ以前に行われたすべての書き込みが見えることが保証されます。読み込みを行った時点で見えるようになります。フィールドからの読み込みはモニタの取得と同様です。通常の方法で並び替えられる可能性があります。「下」に移動することは出来ません。アクセス同士はお互いに並び替えることが出来ません。適切なメモリバリアを張ってくれます。付いていない限りアトミックにアクセスされないことを述べておくべきでしょう。シングルプロセッサ環境であっても、問題が起きる可能性があります。以下はシンプルな、正しくない、単調カウンタの実装です。複数のスレッドから呼ばれるものと仮定します。呼ばれれば、現在の値をどのスレッドからも見れるようにしたいとします。つの操作であるということです。片方の更新は失われるでしょう。シングルプロセッサ環境では正しく動作するようになります。結果が違って見える可能性があります。すれば、この問題を修正できます。この変更によって、明らかに正しいコードになります。残念なことに、ロックの奪い合いが起きるようになってしまいました。これは性能に影響を与えます。