16

Dekker スタイルの同期の失敗は、通常、命令の並べ替えで説明されます。つまり、私たちが書くなら

atomic_int X;
atomic_int Y;
int r1, r2;
static void t1() { 
    X.store(1, std::memory_order_relaxed)
    r1 = Y.load(std::memory_order_relaxed);
}
static void t2() {
    Y.store(1, std::memory_order_relaxed)
    r2 = X.load(std::memory_order_relaxed);
}

次に、ロードをストアで並べ替えて、r1==r2==0.

この種の並べ替えを防ぐために acquire_release フェンスを期待していました。

static void t1() {
    X.store(1, std::memory_order_relaxed);
    atomic_thread_fence(std::memory_order_acq_rel);
    r1 = Y.load(std::memory_order_relaxed);
}
static void t2() {
    Y.store(1, std::memory_order_relaxed);
    atomic_thread_fence(std::memory_order_acq_rel);
    r2 = X.load(std::memory_order_relaxed);
}

フェンスの上に荷物を移動できず、フェンスの下にストアを移動できないため、悪い結果を防ぐ必要があります。

ただし、実験によると、r1==r2==0まだ発生する可能性があります。これについて並べ替えに基づく説明はありますか?私の推論のどこに欠陥がありますか?

4

2 に答える 2

12

私が理解しているように (主にJeff Preshings のブログを読んでから)、 はatomic_thread_fence(std::memory_order_acq_rel)以外の並べ替えを防ぎますStoreLoad。つまり、 をStore後続の で並べ替えることができますLoad。ただし、これはまさにあなたの例で防止する必要がある並べ替えです。

より正確には、atomic_thread_fence(std::memory_order_acquire)は、前の と後続の の並べLoad替えを防ぎます。つまり、フェンスを越えた並べ替えを防ぎます。StoreLoadLoadLoadLoadStore

Anは、任意の先行および先行するatomic_thread_fence(std::memory_order_release)任意の後続の並べ替えを防ぎます。つまり、フェンスを越えた並べ替えを防ぎます。StoreStoreLoadLoadStoreStoreStore

atomic_thread_fence(std::memory_order_acq_rel)は結合を防ぎます。つまり、 、 、および を防ぎますLoadLoadLoadStoreこれは、まだ発生する可能性がStoreStoreあることを意味します。StoreLoad

于 2014-12-03T10:52:31.800 に答える