C++11以降で知られているように、6つのメモリ順序があり、ドキュメントには次のように書かれていstd::memory_order_acquire
ます:
memory_order_acquire
このメモリ順序での読み込み操作は、影響を受けるメモリ位置で取得操作を実行します。現在のスレッドのメモリ アクセスは、この読み込みの前に並べ替えることができません。これにより、同じアトミック変数を解放する他のスレッドでのすべての書き込みが、現在のスレッドで確実に表示されます。
1. 非アトミックロードは、アトミック取得ロードの後に並べ替えることができます。
つまり、acquire-atomic-load の後に non-atomic-load を並べ替えることができないという保証はありません。
static std::atomic<int> X;
static int L;
...
void thread_func()
{
int local1 = L; // load(L)-load(X) - can be reordered with X ?
int x_local = X.load(std::memory_order_acquire); // load(X)
int local2 = L; // load(X)-load(L) - can't be reordered with X
}
の後にロードint local1 = L;
を並べ替えることはできますX.load(std::memory_order_acquire);
か?
2. 非アトミック ロードは、アトミック アクワイア ロードの後に並べ替えることができないと考えることができます。
一部の記事には、取得と解放のセマンティクスの本質を示す図が含まれていました。これは簡単に理解できますが、混乱を招く可能性があります。
たとえば、std::memory_order_acquire
一連の Load-Load 操作を並べ替えることができないと考えるかもしれません。非アトミック ロードであっても、atomic-acquire-load の後で並べ替えることはできません。
3. 非アトミックロードは、アトミック取得ロードの後に並べ替えることができます。
明確化されていることは良いことです: セマンティクスを取得することで、プログラム順序でそれに続く読み取りまたは書き込み操作による読み取り/取得のメモリの並べ替えが防止されます。http://preshing.com/20120913/acquire-and-release-semantics/
しかし、次のことも知られています: 厳密に順序付けされたシステム ( x86、SPARC TSO、IBM メインフレーム) では、大部分の操作で解放と取得の順序付けが自動的に行われます。
また、34 ページの Herb Sutter には次のように示されています。
4. つまり、atomic-acquire-load の後に non-atomic-load を並べ替えることはできないと考えることができます。
つまり、x86 の場合:
- リリースと取得の順序付けは、ほとんどの操作で自動的に行われます
- 読み取りは、どの読み取りでも並べ替えられません。(任意 - つまり、古いかどうかに関係なく)
では、C++11 でアトミック取得ロードの後に非アトミックロードを並べ替えることができますか?