9

私の前の質問と同様に、このコードを検討してください

-- Initially --
std::atomic<int> x{0};
std::atomic<int> y{0};

-- Thread 1 --
x.store(1, std::memory_order_release);

-- Thread 2 --
y.store(2, std::memory_order_release);

-- Thread 3 --
int r1 = x.load(std::memory_order_acquire);   // x first
int r2 = y.load(std::memory_order_acquire);

-- Thread 4 --
int r3 = y.load(std::memory_order_acquire);   // y first
int r4 = x.load(std::memory_order_acquire);

この場合、C ++ 11メモリモデルの下で奇妙な結果 r1==1, r2==0と可能性はありますか? r3==2, r4==0すべてを に置き換えるとどうなりstd::memory_order_acq_relますstd::memory_order_relaxedか?

x86 では、このような結果は禁止されているようです。この SO の質問を参照してください。ただし、一般的な C++11 メモリ モデルについて質問しています。

おまけの質問:

C++11 では奇妙な結果std::memory_order_seq_cstが許容されないことに、私たちは皆同意しています。さて、Herb Sutter は彼の有名な-weapons talk @ 42:30 で言いましたが、それ-loads may not move before -writesのようなものです。上記の例のこの追加の制約が、奇妙な結果を防ぐ方法がわかりません。誰でも説明できますか?atomic<>std::memory_order_seq_cststd::memory_order_acq_rel std::memory_order_acquirestd::memory_order_release

4

4 に答える 4

1

この場合、C ++ 11メモリモデルの下で奇妙な結果 r1==1, r2==0と可能性はありますか?r3==0, r4==2

はい。C++ メモリ モデルでは、このような奇妙な結果が可能です。

すべてを に置き換えるとどうなりstd::memory_order_acq_relますstd::memory_order_relaxedか?

memory_order_acquireallとmemory_order_releasebyを置き換えてmemory_order_relaxedも、コードは何も変わりません。

std::memory_order_seq_cstと同じですstd::memory_order_acq_relが、std::memory_order_acquire-loads は -writes の前に移動しない場合がありstd::memory_order_releaseます。上記の例のこの追加の制約が、奇妙な結果を防ぐ方法がわかりません。

acquire-loads は -writes の前に移動しない場合がありreleaseます。」は、順次整合性の制約の 1 つの側面を示しています ( memory_order_seq_cst)。

seq_cstC++ メモリ モデルでは、acq_relセマンティクスが保証されるだけであり、すべての seq_cstアトミック アクセスには多かれ少なかれ「全体的な順序」があります。このような「全順序」が存在する場合、すべてのアトミック アクセスがシングル スレッド上でインターリーブされた順序で実行されるため、奇妙な結果を得ることができません。seq_cst

の質問は単一の原子変数の「一貫性」を扱い、この質問はすべての原子変数の「一貫性」を尋ねます。C++ メモリ モデルは、単一のアトミック変数の直感的なrelaxed一貫性を、最も弱い順序付けでも保証し ( )、デフォルトの順序付けが続く限り、異なるアトミック変数の「順次一貫性」を保証します ( seq_cst)。明示的にseq_cst順序付けされていないアトミック アクセスを使用すると、指摘したように奇妙な結果になる可能性があります。

于 2015-01-07T06:31:56.237 に答える