【问题标题】:Why does compare_exchange_strong fail with std::atomic<double>, std::atomic<float> in C++?为什么 compare_exchange_strong 在 C++ 中因 std::atomic<double>、std::atomic<float> 而失败?
【发布时间】:2021-06-08 12:25:39
【问题描述】:

我正在阅读 C++ Concurrency in Action 第 5 章。 本章说,

请注意,尽管您可以使用 std::atomic 或 std::atomic,因为内置浮点类型确实满足与 memcpy 和 memcmp 一起使用的标准,但在compare_exchange_strong 的情况。即使旧存储值的值与比较数相等,如果存储值具有不同的表示形式,操作也可能失败。请注意,浮点值没有原子算术运算。如果您将 std::atomic 与定义了相等比较运算符的用户定义类型一起使用,并且该运算符与使用 memcmp 的比较不同,那么您将获得与 compare_exchange_strong 类似的行为 - 操作可能会失败,因为否则 -相等的值有不同的表示。

但我不明白为什么会这样。

  1. 如果float和double都可以使用memcpy和memcmp,那么做compare_exchange_strong这样的原子操作有什么问题?

  2. 我也不能使用 compare_exchange_weak 吗?

  3. 以上段落,“差异表示”是什么意思?

【问题讨论】:

    标签: c++ c++11 concurrency atomic


    【解决方案1】:

    IEEE-754 浮点数使用有符号/幅度格式来确定尾数的符号。也就是说,有一个符号位,然后有代表一个正数的位。如果设置了符号位,则该数字被解释为负数。

    当然,如果所有的数字(和指数)位都是 0,并且符号位被设置,那么这会产生“数字”-0.0。就现实世界的人类数学而言,没有“负0”。所以从逻辑上讲,这样的数字应该被视为等于+0.0。而普通的浮点比较逻辑正是这样做的。但这两个等价值以不同的二进制表示形式存储;一个设置了符号位;另一个没有。

    因此,如果您比较两个浮点值的二进制表示(atomic_compare_* 操作将执行此操作),则 -0.0 将被视为等于 +0.0。

    还有其他情况下 IEEE-754 相等性测试可能出错,但这是最简单的解释。

    【讨论】:

    • 好像和那个double一样的问题,float不能和==操作符比较。如果是这样, compare_exchange_weak 也可能有问题。问题1、2已解决。 “问题3中的不同表示”是否意味着相同数量的数字可以用不同的位表示来表示,当涉及到double,float时,例如+0.0和-0.0?
    • @myoldgrandpa: "好像和那个double一样的问题,float不能和==操作符比较" 你可以用==比较float。由于数值精度问题,您只是不应该。但是 +0.0 和 -0.0 在 IEEE-754 中比较相等。只是您无法进行二进制比较来获得该结果。 “相同数量的数字可以用不同的位表示”这就是我在第二段最后一句所说的字面意思。
    猜你喜欢
    • 2012-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-02
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多