単項演算子の原子挙動

どこかに私は単項演算子が本質的にアトミックなので、彼らはそれがマルチスレッド環境でそのまま使用できることを読んだ。同じことを確認するために、私は2つの別々のプログラムを書きました。

  1. 変数xを使用し、単項演算子++ xを使用して増分しました。
  2. 変数xを使用し、x = x + 1を使用して増分しました。

両方のプログラムの逆アセンブリを比較したところ、違いはありません。これにあなたの入力を提供してください。

2
あなたの変数は原子的ですか? C ++の std :: atomic 型など。
追加された 著者 Daniel Langr,
ある命令がアトミックであるかどうかは関係ありませんが、正しい同期か競合かのどちらかです。
追加された 著者 Baum mit Augen,
私があなたがそれを読んだところはどこでもそれが同時性の文脈で使われたものと異なった意味で「アトミック」という言葉を使ったと思う。それとも、彼らは完全に間違っていたので、あなたはそこで見たものを信用してはいけません。
追加された 著者 molbdnilo,
私自身へのフォローアップ:並行性が至る所に現れる前は、接頭辞 ++ が "変数をアトミックにインクリメントしてその新しい値を返す"と言うのは珍しいことではありませんでした。 構文的は1つの操作にすぎません - それが不可分であるというわけではありません。
追加された 著者 molbdnilo,
++ x がアトミックであるからといって、 x = x + 1 ではありませんか? (論理的な観点からは、とにかく ++ x が常に不可分であるとは思わない)
追加された 著者 Ctx,
変数はメモリ内に常駐でき、したがって複数の命令(ロード、追加、格納)を必要とするので、それらは自動的にアトミックではありません
追加された 著者 Simon F,

7 答え

どこかで、単項演算子は本質的にアトミックであり、マルチスレッド環境でそのまま使えるということを読んでいます。

That source is completely wrong. You need to use std::atomic (or the C equivalent) to achieve atomicity – unary operations are not special.


両方のプログラムの分解を比較したところ、違いはありませんでした

それは生成された操作がアトミックであるという意味ではありません。まともなコンパイラは x = x + 1++ x に最適化するため、違いはありません(組み込み型を想定)。

8
追加された

単項演算子が必ずアトミックであるという主張は神話です。

たとえば、 ++ x では x への読み書きが必要であるため、データ競合の可能性があります。

++ xx = x + 1 と同じコードにコンパイルされるという事実は関係ありません。

データの競合を避けたい場合は、アトミックタイプを使用するか、適切なアトミックタイプが利用できない場合は相互排除ユニットを使用してください。誤解を避けるために、 int は必ずしもアトミック型ではありません。

3
追加された
あなたは単項です。
追加された 著者 Sombrero Chicken,

どこかで、単項演算子は本質的にアトミックなので、彼らは   マルチスレッド環境でそのまま使用できます。

それは間違っています。たとえば、 x ++ には x の読み込み、 x の追加、保存が必要です。これらの指示は本質的にアトミックではありません。

2
追加された

違います。たとえそうであっても、 https://en.cppreference.com/w/cpp/atomic/atomic#Type_aliases 次に持っていますか?

私は彼らがおそらく意味しているのは、そのような操作の計算は通常非常に細かいので競合状態になることはないだろうということです。

1
追加された

操作stronglrの原子性は、ターゲットシステムによって異なります。 RISCマイクロコントローラのようなRMWシステムでは、単項操作はアトミックではないかもしれません。

この質問に対する一般的な答えは1つもありません。

1
追加された
それは(他の人がそうであるように)決して不可分ではあり得ないと主張していないので、(少し簡潔ではあるが)良い答え。しかし、この質問には「単一の一般的な答え」があります。「いいえ、単項演算子は本質的に原子的ではありません」。
追加された 著者 Ctx,

生成されたコードを仮定します。1つの命令しか生成されない場合はアトミック、それ以外の場合はノーとなります。

In your case this supposes the target processor has the instruction inc

and the compiler will produce it.
0
追加された

When writing cross platform C++, you only have atomic behavior when using std::atomic<>.

確かに、Intel 64ビットのような特定のプラットフォームでは、プロセッサは inc がアトミックであることを保証します。しかし、これに依存するコードを書かないでください。あなたの将来のデバッガとして、どのデータがスレッド間で共有されることを意図しているか、どれがそうではないかを知りたいのです。

Using std::atomic might be a bit more work to write, however, it does guarantee that everything behaves atomically (on every platform) by either falling back to the platform requirements (std::atomic::is_lock_free), or by explicitly putting a lock around the access. It as well insert guards in order to make sure that the caches of the other processor cores are invalidated (if the platform requires this).

Intel 64ビットの場合、実際にはこれで同じアセンブリが得られるはずです。そうでない場合は、コンパイラにバグを記録します。

同時に、intを使ったいくつかの操作はアトミックではないかもしれません(operator * =)、 std :: atomic は単にそれらの操作を保持していないので、それらを正しく扱う必要があります。

ちなみに ++ xx = x + 1 は異なる操作ですが、同じアセンブリに最適化されている可能性があります。非アトミックプラットフォームの要件を考えると、2番目は突然解決するのに数日かかるバグです。

0
追加された