2016-04-24 8 views
14

次のようにstd::memory_order_acquirestd::memory_order_releaseの私の理解では、次のとおりです。メモリーフェンス:取得/ロードおよび/ストアを解放

獲得にはメモリが取得フェンスは、フェンスの前に並べ替えることができ後に表示されてアクセスしていないことを意味し。

リリースにはメモリが解放フェンスはフェンスの後に並べ替えることができ前に表示されてアクセスしていないことを意味します。

C++ 11アトミック・ライブラリで特に、取得フェンスはロード操作に関連付けられていますが、リリース・フェンスはストア操作に関連付けられています。明確にするために

、C++ 11 <atomic>ライブラリーは、2つの方法でメモリフェンスを指定することができます:

x.load(std::memory_order_acquire); 

それとも:あなたのような、原子操作への追加の引数としてフェンスを指定しますかstd::memory_order_relaxedを使用するなど、個別にフェンスを指定することができます。

x.load(std::memory_order_relaxed); 
std::atomic_thread_fence(std::memory_order_acquire); 

私は、取得の上記の定義を与え、解放している理解していない、なぜC++ 11は、具体的取得を関連付けないの負荷のリリースのストア?はい、私はリリース/ストアで取得/負荷をスレッド間で同期するために使用する方法を示す多くの例を見てきましたが、一般的にはフェンスを獲得するという考え方(ステートメントの後にメモリの並べ替えを防ぐ)フェンス(文の前にメモリの順序を変更しないようにする)は、ロードとストアの考え方とは正反対です。

それでは、なぜ、例えば、コンパイラは私が言わせません。

x.store(10, std::memory_order_acquire); 

私はmemory_order_relaxedを使用して上記を達成することができます実現し、その後、別のatomic_thread_fence(memory_order_acquire)声明が、再び、なぜできmemory_order_acquireと直接店舗を使用していますか?

x = 10などのストアがになる前に、の前に他のスレッドに影響する可能性のあるストアが確実に実行されている可能性があります。

+1

、あなたは(取得する準備ができて)共有リソースが消費のために準備ができているかどうかを確認するために、原子を読んで、あなたは、共有リソースを使用する準備ができていることを示すために、原子を書く(へリソースを解放する)。アトミックガーディングがチェックされる前に共有リソースの読み込みを望んではいけません。アトミックが書き込まれた後、解放を示す共有リソースの初期化を望んではいけません。 –

+0

この例では、 'atomic_thread_fence(std :: memory_order_acquire)'のみが真のフェンスです。 _標準の「** 1.10:5マルチスレッド実行とデータ競合[intro.multithread] **」を参照してください(n3797のドラフトを引用しています)_ "関連付けられたメモリ位置のない同期操作はフェンスであり、これとは対照的に、 'x.load(std :: memory_order_acquire)'は_atomic操作であり、 'x'で_acquire_操作を実行すると、_synchronization operation_値がストアに一致した場合_release_をxに格納します。 – amdn

+0

はじめに、標準(ドラフトn3797)では、取得操作をロードに制限したり、ストア操作をストアに解放することはできません。それは残念です。 memory_order_acquire、memory_order_acq_rel、およびmemory_order_seq_cst:ロード操作が、影響を受けたメモリ位置で取得操作を実行します。 "_ and _" memory_order_release ** 29.3:1 Order and consistency [atomics.order] **に移動する必要があります。 、memory_order_acq_rel、およびmemory_order_seq_cst:ストア操作は、影響を受けたメモリ位置で解放操作を実行します。 "_ – amdn

答えて

10

私はいくつかのデータを書きますが、次にデータが準備完了であるという指示を書きます。データが準備されているという表示を見る他のスレッドは、データそのものの書き込みを見ることができません。したがって、先行書き込みはその書き込みを通過できません。

私はいくつかのデータが準備ができていることを読んでいると言います。それは、データの準備ができているのを見て、読んだ後に私が見た後に起こるすべての読書が不可欠です。したがって、後続の読み取りはその読み取りの後ろに移動することはできません。

同期書き込みを行うときは、通常、同期書き込みを確認したすべての書き込みが表示されていることを確認する必要があります。そして、あなたが同期読み取りを行うときは、通常、同期読み取り後に読み取りを行う必要があります。

あるいは、別の方法でそれを置くためには、取得には、通常、あなたが取るか、またはリソースにアクセスできることを読んで、その後の読み取りと書き込みが前に移動してはいけません。リリースは通常、リソースの処理が完了した書き込みであり、先行する書き込みはその後に移動してはいけません。

-1

std::memory_order_acquireフェンスだけこうしてmemory_order_acquire負荷が実行された後ときにストアが他のスレッドのために表示されている保証はないでき、フェンス結局負荷操作がフェンスの前に任意負荷操作の前に並べ替えされていない保証します。このため、memory_order_acquireはストア操作ではサポートされていません。ストアの取得を実現するにはmemory_order_seq_cstが必要な場合があります。代替案として

、あなたは店の前に並べ替えていないすべての負荷を確実にするために

x.store(10, std::memory_order_releaxed); 
x.load(std::memory_order_acquire); // this introduce a data dependency 

を言うかもしれません。ここでもフェンスは機能しません。それだけアトミック命令はなく、フェンスの前と後のすべての命令に順序を相対的に保証ので

また、アトミックオペレーションのメモリ順序は、メモリフェンスよりも安価であり得ます。

formal descriptionや詳細についてexplanation参照してください。典型的なロックフリーアルゴリズムで

+0

最初の文は正しくありません(-1)。実際には、*取得フェンスに続くメモリアクセス*は、そのフェンスに先行するロード操作と並べ替えることはできません。 (逆に、リリースフェンスに先行する任意のメモリアクセスは、フェンスに続く任意のストア動作と並べ替えることができない。)フェンスが 'memory_order_release'を有する任意の原子操作又はフェンス後に発生した後 –

+0

@JohnWickersonは実際' memory_order_releaxed'のみ負荷を保証します。フェンス後の店舗での注文はありません。 ['atomic_thread_fence'](http://en.cppreference.com/w/cpp/atomic/atomic_thread_fence)のatomic-fence同期セクションを参照してください。 – user1887915

+0

興味深い!あなたが参照しているcppreference.comのウェブサイトが実際に間違っていると私は信じています。公式のC11標準によると、リリースと取得フェンスは、私が記述した方法で動作します。 –

関連する問題