2016-12-27 12 views
3

1つのアトミック変数とstd::memory_order_seq_cstを使用する場合、非アトミック操作の順序が変更されないことが保証されていますか?memory_order_seq_cstは非アトミック操作とどのように同期しますか?

私は

std::atomic<bool> quux = {false}; 

void foo() { 
    bar(); 
    quux.store(true, std::memory_order_seq_cst); 
    moo(); 
} 

を持っている場合たとえば、bar()storeの呼び出し後に並べ替えを取得しないことが保証され、かつmoo()はで、限り、私はstd::memory_order_seq_cstを使用すると、storeの呼び出しの前に並べ替えを取得していません少なくとも別のスレッドの観点から?

また、別のスレッドから実行した場合、以下の仮定は有効ですか?

if(quux.load(std::memory_order_seq_cst) == true) { 
    // bar guaranteed to be called; its side-effects are visible 
    // moo might have been called, but is not guaranteed to 
} else { 
    // bar might have been called, but is not guaranteed to 
    // moo might have been called, but is not guaranteed to 
} 

私はbarmooどちらもアトミック操作、ミューテックス、ロック、フェンスや他の同期機能を使用することを想定しています。

答えて

3

1つのアトミック変数とstd::memory_order_seq_cstを使用する場合、非アトミック操作の順序が変更されないことが保証されていますか?

標準このhttp://en.cppreference.com/w/cpp/atomic/memory_orderにかなり明確である:

memory_order_seq_cstこのメモリ順序を有する任意の動作が存在取得動作及びリリース動作、プラス単一の全順序の両方されているすべてのスレッドすべての変更を同じ順序で観察してください

memory_order_acquireこのメモリのロード操作では、影響を受けるメモリ上で取得操作が実行されます。rea dsまたは現在のスレッドの書き込みは、このロードの前に並べ替えることができます

memory_order_releaseこのメモリオーダーのストア操作では、解放操作が実行されます。現在のスレッドの読み取りまたは書き込みは、このストアの後に再順序付けできません。

つまり、memory_order_seq_cst操作の回りにロードまたはストア(非アトミックとアトミックの両方)を並べ替えることはできません。


限り、私はSTDを使用して、店舗の呼び出し後に並べ替えを取得しないことを保証し、moo()は店の呼び出しの前に並べ替えを取得していない:: memory_order_seq_cstを、少なくともの観点からbar()です別のスレッド?

barmooの定義は、現在の翻訳単位で使用できない場合、コンパイラは、したがって、これらの機能は、メモリの負荷を行い、および/または(メモリへのI/Oや店舗を行う)の副作用があることを前提とし、かつmemory_order_seq_cst操作で並べ替えることはできません。

定義が利用可能で、関数がI/Oまたはメモリのロード/ストアを実行しない場合は、それらを並べ替えることができます。これらは、pure functionsまたは何もしない関数で、voidまたは定数を返します。

+0

Nitpickingですが、cppreference.comは優れていますが、ISO規格ではありません。 – Zeta

+0

@Zetaあなたは正しいです。私はcppreference.comがかなり正確であることを見つけましたが、それは標準のコピーではないので省略されているかもしれません。 –

-2

最も厳密なメモリ順序が使用されているため、ファンクションバーとムーを、それぞれストアの前または前に並べ替えることはできません。

if-elseの場合の結論は正しくありません。

if(quux.load(std::memory_order_seq_cst) == true)がtrueと評価された場合、関数バーはすでに呼び出しを完了しています。ムーへの呼び出しの順序は決めることができません。終了しているか、開始されていないか、コールの途中にある可能性があります。

上記の式がfalseと評価された場合、両方の関数の順序を決定することはできません。式がfalseに評価された瞬間に、関数mooはまだ呼び出されていませんが、その直後に呼び出されて、実行がelse節に進む前に呼び出される可能性があります。いったんelse節に入ると、関数mooの状態は前の段落と同じです(それは決めることができません)。

0

@ Maximでリンクされているhttp://en.cppreference.com/w/cpp/atomic/memory_orderのリンクによると、memory_order_seq_cstに関してエラーがあります。上記のテキストはmemory_order_acq_relと交換されます。 memory_order_seq_cstのテキスト:

memory_order_seq_cst:このメモリーオーダーのロード操作は、取得操作を実行し、ストアは解放操作を実行し、読み取り - 変更 - 書き込みは、取得操作と解放操作の両方を実行します。すべてのスレッドが同じ順序ですべての変更を観察する順序が存在します(下の順に一貫した順序を参照してください)。

したがって、ストア操作は、moo()をフェンスの前に並べ替えることができます。

関連する問題