2016-07-19 7 views
1
std::atomic<int> cnt = {2}; 

thread 1: 
    doFoo(); 
    if (cnt.fetch_sub(1, std::memory_order_relaxed) == 1) { 
     doBazz(); 
    } 

thread 2: 
    doBar(); 
    if (cnt.fetch_sub(1, std::memory_order_relaxed) == 1) { 
     doBazz(); 
    } 

doFoo()doBar()は常にdoBazz()より前に発生することがありますか?原子基準のカウントのためにmemory_order_relaxedを指定したfetch_sub?

+0

memory_order_relaxedを使用しています。つまり、メモリの順序付けが実行されていません。そのような保証はありません。 – 2501

答えて

-1

あなたが示したコードではメモリの順序は全くないため、保証はではなく、が成立します。しかし、あなたがいるとそれが動作していどこrelease sequencefetch_sub一部を行うことで、リラックスした順序付けを使用することが可能である:

std::atomic<int> cnt{0}; 
cnt.store(2, std::memory_order_release); // initiate release sequence (RS) 

//thread 1: 
    doFoo(); 
    if (cnt.fetch_sub(1, std::memory_order_relaxed) == 1) { // continue RS 
     std::atomic_thread_fence(std::memory_order_acquire); // synchronizes with RS 
     doBazz(); 
    } 

//thread 2: 
    doBar(); 
    if (cnt.fetch_sub(1, std::memory_order_relaxed) == 1) { // continue RS 
     std::atomic_thread_fence(std::memory_order_acquire); // synchronizes with RS 
     doBazz(); 
    } 

または

void doBazz(); 

std::atomic<int> cnt{0}; 
cnt.store(2, std::memory_order_release); // initiate release sequence (RS) 

//thread 1: 
    doFoo(); 
    if (cnt.fetch_sub(1, std::memory_order_relaxed) == 1) { // continue RS 
     doBazz(); 
    } 

//thread 2: 
    doBar(); 
    if (cnt.fetch_sub(1, std::memory_order_relaxed) == 1) { // continue RS 
     doBazz(); 
    } 

void doBazz() { 
    std::atomic_thread_fence(std::memory_order_acquire); // synchronizes with RS 
    // ... 
} 

doFoo()doBar()は常にdoBazz()前に起きていることこれらの保証。でも緩和メモリモデルと、外の薄い空気の値が最初にxとyはゼロで、例えば、円独自の計算に依存することが許可されていない

+0

Acquireはコードが操作の下を移動するのを防ぎません。 – 2501

+0

あなたはそれを防ぐ方法がわかりません。 – 2501

+0

@ 2501:C++メモリモデルでは、緩和されていないアトミック操作はすべて、コンパイラの障壁として機能します。 – ildjarn

-1

http://en.cppreference.com/w/cpp/atomic/memory_order

// Thread 1: 
r1 = x.load(memory_order_relaxed); 
if (r1 == 42) y.store(r1, memory_order_relaxed); 
// Thread 2: 
r2 = y.load(memory_order_relaxed); 
if (r2 == 42) x.store(42, memory_order_relaxed); 

は、r1 == r2 == 42を生成することはできません.42からyまでのストアは、xへのストアが42を格納する場合にのみ可能です。これは循環に依存してストアを格納する42になります。これは仕様では技術的に許可されていましたが、実装者には推奨されませんでした。

memory_order_relaxedを指定しても、まだ実行できない実行順序があります。

cnt.fetch_sub(1, std::memory_order_relaxed) == 2 

cnt.fetch_sub(1, std::memory_order_relaxed) == 1 

右の前に起こるべきであると私には見えますか?したがって、doFoo()とdoBar()の両方がdoBazz()の前に発生する必要があります。

関連する問題