当前位置: 首页 > 知识库问答 >
问题:

使用C++原子的奇怪行为

巩俊远
2023-03-14

这个程序打印00,但是如果我注释掉a.store和b.store,而取消注释a.fetch_add和b.fetch_add,这做了完全相同的事情,即都设置了a=1,b=1的值,我永远不会得到00。

  • 是我错过了什么,还是“00”按标准永远不会出现?

下面打印00。

// g++ -O2 -pthread axbx.cpp  ; while [ true ]; do ./a.out  | grep "00" ; done
#include<cstdio>
#include<thread>
#include<atomic>
using namespace std;
atomic<int> a,b;
int reta,retb;

void foo(){
        //a.fetch_add(1,memory_order_relaxed);
        a.store(1,memory_order_relaxed);
        retb=b.load(memory_order_relaxed);
}

void bar(){
        //b.fetch_add(1,memory_order_relaxed);
        b.store(1,memory_order_relaxed);
        reta=a.load(memory_order_relaxed);
}

int main(){
        thread t[2]{ thread(foo),thread(bar) };
        t[0].join(); t[1].join();
        printf("%d%d\n",reta,retb);
        return 0;
}

下图从不打印00

// g++ -O2 -pthread axbx.cpp  ; while [ true ]; do ./a.out  | grep "00" ; done
#include<cstdio>
#include<thread>
#include<atomic>
using namespace std;
atomic<int> a,b;
int reta,retb;

void foo(){
        a.fetch_add(1,memory_order_relaxed);
        //a.store(1,memory_order_relaxed);
        retb=b.load(memory_order_relaxed);
}

void bar(){
        b.fetch_add(1,memory_order_relaxed);
        //b.store(1,memory_order_relaxed);
        reta=a.load(memory_order_relaxed);
}

int main(){
        thread t[2]{ thread(foo),thread(bar) };
        t[0].join(); t[1].join();
        printf("%d%d\n",reta,retb);
        return 0;
}

再看看这个,多线程原子a b打印00 for memory_order_refield

共有1个答案

路奇
2023-03-14

两种情况我都得10分。第一个线程总是运行得更快,a==1!但如果向foo()添加其他操作

#include<cstdio>
#include<thread>
#include<atomic>
using namespace std;
atomic<int> a,b;
int reta,retb;

void foo(){

    int i=0;
    while(i < 10000000)
        i++;

    a.fetch_add(1,memory_order_relaxed);
    //a.store(1,memory_order_relaxed);
    retb=b.load(memory_order_relaxed);
}

void bar(){
    b.fetch_add(1,memory_order_relaxed);
    //b.store(1,memory_order_relaxed);
    reta=a.load(memory_order_relaxed);
}

int main(){
    thread t[2]{ thread(foo),thread(bar) };
    t[0].join(); t[1].join();
    printf("%d%d\n",reta,retb);
    return 0;
}

你会收到“01”!

 类似资料:
  • 也许有些东西我没有完全理解,但是在阅读了“自动使用decltype”之后 让我们假设我们有 我定义了两个lamba(一个带有auto,另一个正确转发auto) 结果是一样的:f(s)和g(s)调用size(constd::string 我的问题是:为什么会发生这种情况?难道不应该只有第二个lambda能够区分左值和右值吗?我期望第一个lambda(f())调用两倍大小(const std::str

  • 我有以下代码来解析一个JSON文件: 要处理以下JSON文件: 如果我执行此代码,我将收到以下错误: 所以我开始一步一步地调试应用程序,看看part processing()中的哪个代码部分抛出了这个异常。令人惊讶的是,那里的所有代码都正常执行:没有抛出异常,也没有返回结果I except。 更让我惊讶的是,当我稍微改变第一种方法的代码时,它可以在不产生异常的情况下工作。 我不知道println方

  • 根据文献记载 must_not子句(query)不能出现在匹配的文档中。 我有如下查询: 在我的elasticsearch存储库中有两个URI 1) 编辑这里是我的映射

  • 问题内容: 我在GregorianCalendar类中遇到一个奇怪的行为,我想知道我是否真的做得不好。 仅当初始化日期的月份的实际Maximum大于我将日历设置为的月份时,才追加此值。 这是示例代码: 我知道问题是由于日历初始化日期是31天(可能是5月),与设置为2月(28天)的月份混淆了。修复很容易(只需在设置年和月之前将day_of_month设置为1),但是我想知道这确实是想要的行为。有什么

  • 问题内容: 我正在为一个问题而苦苦挣扎,我不明白为什么它不起作用。如何通过将变量传递并转换为? 为什么在顶部代码段中不起作用,但在行下方的底部代码段中起作用? 唯一的区别似乎是添加了一个额外的变量,该变量也被键入为? 问题答案: 该是一种原始类型,同时是一个普通的Java类。您不能在原始类型上调用方法。但是该方法在上可用,如javadoc中所示 有关这些原始类型的更多信息,请参见此处

  • 问题内容: 为什么的到哪里去了? 问题答案: 删除任何字符,并从字符串的开头和结尾。