是否可以在C++中创建原子向量或数组?

rai*_*bow 20 c++ arrays multithreading vector atomic

我有一些代码int[]在一个线程中使用int()数组,每秒激活一次.

我使用lock()from std::mutex来锁定这个线程中的数组.

但是我想知道是否有办法创建一个原子数组(或向量)来避免使用互斥锁?我尝试了几种方法,但编译器总是以某种方式抱怨?

我知道有一种方法可以创建一个原子数组,但这是不一样的.

Mar*_*ica 42

实际上,在CPU级别,有一些指令可以自动更新int,一个好的编译器将使用它们std::atomic<int>.相比之下,有没有指令可以原子更新INTS的载体(我所知道的任何架构),所以也就是一些互斥排序的地方.你不妨让它成为你的互斥体.


对于尚未使用互斥锁编写代码的未来读者:

你不能创建std::atomicint[10],因为这会导致它返回一个数组的函数-你可以没有这些.你能做什么,有一个std::atomic<std::array<int,10>>

int main()
{
  std::atomic<std::array<int,10>> myArray;
}
Run Code Online (Sandbox Code Playgroud)

请注意,编译器/库将在底层创建一个互斥锁以使其成为原子.请注意,这不符合您的要求.它允许您以原子方式设置整个数组的值.

不会让你阅读整个阵列,更新一个元素,整个阵列写回原子.

读取和写入将是单独原子的,但另一个线程可以介入读取和写入之间.

你需要互斥锁!

  • 值得一提的是,这个阵列和巧克力茶壶一样有用.您所能做的就是获取整个阵列的副本或从副本中替换整个阵列. (13认同)
  • @ tobi303:嗯.根据cppreference,平凡可复制类型的数组是可以轻易处理的.*可能*表示cppreference中存在错误,或者标准中存在缺陷.要求库允许你实例化`std :: atomic <int [10]>`当无法获取值时(因为`运算符T`必须返回`int [10]`)是没有意义的. (2认同)

The*_*ist 6

您可以将数组放在原子中,但不能直接放入.像其他答案解释你可以使用std::array.我回答了这个问题并解释了如何为结构做类似的事情.

说完了并解释了技术可行性,我必须告诉你一些其他的事情:

请不要这样做

原子变量的力量来自于某些处理器可以用一条指令执行操作的事实.C++编译器将尝试在一条指令中进行原子操作.如果它失败了,它将启动一个总线锁,就像一个全局锁定一切,直到该阵列被更新.它相当于一个锁定程序中所有变量的互斥锁.如果您担心性能,请不要这样做!

因此,对于您的情况,互斥量并不是一个坏主意.至少你可以控制什么是关键并提高性能.

  • 公交车锁:你有没有引用它?当然,在引擎盖下创建一个互斥体将更容易实现(并且性能更高). (2认同)
  • 如何做呢?简单的。`std::atomic` 的成员函数都不允许直接访问底层值,因此给每个 `std::atomic` 一个互斥锁,在每个成员函数的开头锁定互斥锁,在结束时释放它。我有一种“感觉”,您可能记错了某些架构如何在例如单词上实现原子操作。 (2认同)
  • 我觉得“如果失败,它将启动总线锁定”并不完全正确。看看`atomic::load`的签名: http://www.cplusplus.com/reference/atomic/atomic/load/ 可以指定`memory_order_xxx` (2认同)