菜鸟小田 2023-05-21 01:48 采纳率: 40%
浏览 33
已结题

C++无锁原子变量atomic的compare_exchange_strong问题

今天在维护之前的无锁容器的时候出现了一个很奇怪的bug,在C++20时可以正常使用,在C++17时就会出现异常,最终debug把问题定位并缩小在atomic的compare_exchange_strong中,但我发现了一件非常恐怖的事情,仿佛是我写代码经历了量子危机。
有以下代码:

#include <atomic>
#include<iostream>
using namespace std;
struct MyStruct {
    int a;
    double b;
};
int main() {
    std::atomic<MyStruct> myAtomic{ MyStruct{1, 2.0} };
    MyStruct expected{ 1, 2.0 };
    MyStruct desired{ 2, 3.0 };
    bool ok=myAtomic.compare_exchange_strong(expected, desired);
    cout << ok << endl;
    return 0;
}

运行上面一段代码,在肉眼观察下我们应该会推测应该会输出1,因为原子变量和预期值相等,交互应该会成功,但是奇怪的一幕出现了,我的Visual Studio C++17编译会输出0。嗯,我开始困惑,把编译器调回C++20,又正常输出1了。
后面我又把编译器调回了C++17 尝试找出问题所在,后面更恐怖的事情发生了,当我在compare_exchange_strong后面添加一句

    cout << myAtomic.load().a << " " << myAtomic.load().b << endl;

恐怖的事情发生了,这个结果输出了2 3 \n 1 对,ok又变成了true,我甚至一度怀疑我眼花了,把这句又删除了,输出又变成了0,对ok又变成了false,难道我对这个原子变量是否进行观测还会还会影响compare_exchange_strong的执行?我一度又检测了代码的内存次序,强制调整成std::memory_order_seq_cst,问题依然如此。
好的,我甚至开始怀疑是不是编译时内存次序还有什么隐秘的问题,我把上面的观测代码放到输出ok后面,输出依然是1 \n 2 3 对,ok又变成true了,仿佛是量子力学的观察者效应。希望强者给我一些解答,这是否是VS C++17标准库的缺陷还是我的代码出现了什么问题?

  • 写回答

2条回答 默认 最新

  • 关注

    内存对齐一下

    struct MyStruct
    {
        int64_t a;
        double b;
    };
    
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 5月30日
  • 已采纳回答 5月22日
  • 创建了问题 5月21日

悬赏问题

  • ¥100 求一个,王者荣耀查询隐藏战绩的教材,爬虫代码
  • ¥60 Cocos creator缓动问题
  • ¥40 微信小程序 使用vant组件ActionSheet 下拉面板,内容区域滚动会触发。scroll-view自定义下拉刷!即使设置停止下拉刷新也不行。
  • ¥15 专业问题提问,7月5号2点之前
  • ¥25 使用cube ai 导入onnx模型时报错
  • ¥15 关于#微信小程序#的问题:用一个网页显示所有关联的微信小程序数据,包括每个小程序的用户访问量
  • ¥15 root的安卓12系统上,如何使apk获得root或者高级别的系统权限?
  • ¥20 关于#matlab#的问题:如果用MATLAB函数delayseq可以对分数延时,但是延时后波形较原波形有幅度上的改变
  • ¥15 使用华为ENSP软件模拟实现该实验拓扑
  • ¥15 通过程序读取主板上报税口的数据