web-dev-qa-db-ja.com

C ++でアトミックベクトルまたは配列を作成することはできますか?

毎秒アクティブ化されるスレッドでint(_int[]_)の配列を使用するコードがあります。

_std::mutex_のlock()を使用して、このスレッドでこの配列をロックします。

しかし、ミューテックスの使用を避けるためにアトミック配列(またはベクトル)を作成する方法があるのだろうか?私はいくつかの方法を試しましたが、コンパイラは常に何とか文句を言いますか?

アトミックの配列を作成する方法があることは知っていますが、これは同じではありません。

20
rainbow

実際には、CPUレベルでintをアトミックに更新できる命令があり、優れたコンパイラーはstd::atomic<int>にこれらを使用します。対照的に、intのベクトルをアトミックに更新できる命令はありません(私が知っているアーキテクチャの場合)。したがって、gotが必要です。どこかのある種のミューテックス。ミューテックスにすることもできます。


ミューテックスでコードをまだ書いていない将来の読者向け:

std::atomicint[10]を作成することはできません。これは、配列を返す関数につながるためです。あなたがcanすることは、std::atomic<std::array<int,10>>

int main()
{
  std::atomic<std::array<int,10>> myArray;
}

コンパイラ/ライブラリは、このアトミックを実現するために、フードの下にミューテックスを作成することに注意してください。さらに、これはあなたが望むことをしないことに注意してください。これにより、配列全体の値をアトミックに設定できます。

Itdoes n'tでは、配列全体を読み取り、1つの要素を更新し、配列全体をアトミックに書き戻すことができます

読み取りと書き込みは個別にアトミックになりますが、別のスレッドが読み取りと書き込みの間に入ることができます。

ミューテックスが必要です!

41
Martin Bonner

配列をアトミックに配置できますが、直接配置することはできません。他の答えと同様に、std::arrayを使用できます。 この質問 と答え、構造体に対して同様のことを行う方法を説明しました。

それを言って、技術的な実行可能性を説明したので、私はあなたに何か他のものを言わなければなりません:

それをしないでください

アトミック変数の力は、一部のプロセッサーが1つの命令で操作を実行できるという事実に由来しています。 C++コンパイラは、1つの命令でアトミック操作を実行しようとします。失敗すると、バスロックを開始します。これは、その配列が更新されるまで、すべてのグローバルロックのようなものです。これは、プログラム内のすべての変数をロックするミューテックスに相当します。パフォーマンスが心配な場合は、そうしないでください!

したがって、あなたの場合、ミューテックスは悪い考えではありません。少なくとも、何が重要かを制御し、パフォーマンスを向上させることができます。