代码之家  ›  专栏  ›  技术社区  ›  Troskyvs

c++11:compare_exchange_weak如何产生“虚假故障”?

  •  2
  • Troskyvs  · 技术社区  · 4 年前

    有没有一种方法可以让我们编写一些代码来为compare_exchange的“弱”版本产生“虚假故障”?而compare_exchange_strong应该可以很好地使用相同的代码?

    我想看看2个api的“弱”和“强”版本之间的真正区别,有什么样的例子吗?

    非常感谢!

    1 回复  |  直到 4 年前
        1
  •  9
  •   Peter Cordes    4 年前

    您需要一个非x86 CPU,通常使用 load-linked / store-conditional 如ARM或AArch64(在ARMv8.1之前)。x86 lock cmpxchg 实现CAS_strong,并且当内存中的值匹配时,您无法削弱它并使其可能失败。

    CAS_ weak可以编译为单个LL/SC尝试;CAS_strong必须编译到LL/SC重试循环,只有在比较为假时才会失败,而不仅仅是来自其他线程对缓存行的竞争。( As on Godbolt ,适用于ARMv8 ldxr / stxr 与ARMv8.1相比 cas )

    让一个线程使用CAS_weak对一个std::atomic变量执行1亿次增量。( https://preshing.com/20150402/you-can-do-any-kind-of-atomic-read-modify-write-operation/ 解释了如何使用CAS重试循环在一个变量上实现任意原子RMW操作,但由于这是唯一的线程写入,CAS_strong将始终成功,我们不需要重试循环。我的Godbolt示例显示了使用CAS_weak与CAS_strong进行单次增量尝试。)

    要使CAS_weak而不是CAS_strong出现虚假故障,请让另一个线程读取相同的变量,或者在同一个缓存行中写入其他内容。

    或者做一些类似的事情 var.fetch_or(0, std::memory_order_relaxed) 以真正获得缓存行的所有权,但以不会影响值的方式。那会的 肯定 导致虚假的LL/SC故障。

    完成后,100M CAS_strong尝试将使变量从0增加到100000000。但是100M CAS_weak尝试将增加到某个较低的值,不同之处在于失败次数。

    推荐文章