【问题标题】:Read a non-atomic variable, atomically?以原子方式读取非原子变量?
【发布时间】:2015-08-13 09:30:44
【问题描述】:

我有一个非原子的 62 位双精度数,它在一个线程中定期递增。这种访问不需要是原子的。然而,这个变量偶尔会被另一个线程读取(而不是写入)。如果我在 64 位边界上对齐变量,则读取是原子的。

但是,有什么方法可以确保在增量过程中不会中途读取变量?我可以调用一个 CPU 指令来序列化管道吗?内存屏障?

我曾想过在我的关键线程中声明变量 atomic 并使用 std::memory_order::memory_order_relaxed(并在稀有线程中使用更严格的内存屏障),但它似乎同样昂贵。

【问题讨论】:

  • 使用<atomic> 设施。其他任何事情都会导致未定义的行为。如果知道对齐的 64 位读取是原子的,那么您可能也可以相信您的编译器也知道这一点。
  • @Kerrek SB:你是对的(尽管库编写者在多线程方面出了名的糟糕,但他们终于赶上了)。但是,在使用 时,需要了解“幕后”发生的事情,否则性能损失可能会很大。 harold 的回答可能被视为为什么在使用原子时某些事情会更快的解释(例如,我希望由于这个事实,许多平台上的良好实现将使 store(load( )+1) 比原子增量快一个数量级,尽管它确实有不同的语义并且并不总是合适的)。

标签: c++ multithreading performance x86 atomic


【解决方案1】:

由于您标记了 x86,这将是特定于 x86 的。

增量本质上是三个部分,读、加、写。增量不是原子的,但是只要变量不越过缓存线边界,它的所有三个步骤(我想添加不算,反正它是不可观察的)它的所有三个步骤(这个条件比必须对齐弱)到它的自然对齐,从 P6 开始就是这样,在四字必须对齐之前)。

所以您已经无法读取撕裂的值。您可以做的最糟糕的事情是在读取变量和写入新值之间覆盖变量,但您只是在读取它。

【讨论】:

  • 对。此外,大多数其他平台(至少那些符合 RMO、PSO 和 TSO 内存模型的平台,以及所有单核单插槽 CPU/MCU)都具有一些读写的特性。固有的原子提供的正确对齐(唯一的区别是原子操作数的最大大小)。 Power 和 ARM可能是个例外。
  • 这就是我的结论。只要我将双精度对齐到 64 位,读取它应该是原子的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-21
  • 1970-01-01
  • 2017-08-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多