C++ 调用线程会在thread.join()之后看到对局部变量的修改吗?

C++ 调用线程会在thread.join()之后看到对局部变量的修改吗?,c++,c++11,concurrency,thread-safety,memory-model,C++,C++11,Concurrency,Thread Safety,Memory Model,在最简单的示例中,假设我有一个启动线程的函数,该函数将局部变量的值设置为true。我们加入线程,然后离开函数 bool func() { bool b = false; std::thread t([&]() { b = true; }); t.join(); return b; } 此函数将返回true,还是行为未定义?是,它必须返回true [thread.thread.member] void join(); 效果:阻塞,直到由*表示的线程完成

在最简单的示例中,假设我有一个启动线程的函数,该函数将局部变量的值设置为true。我们加入线程,然后离开函数

bool func() {
    bool b = false;
    std::thread t([&]() { b = true; }); 
    t.join();
    return b;
}

此函数将返回true,还是行为未定义?

是,它必须返回true

[thread.thread.member]

void join();
效果:阻塞,直到由
*表示的线程完成

同步:由
*表示的线程的完成与([intro.multi-thread])相应的成功
join()
返回同步

因此,在
join
返回调用上下文之前,执行由句柄表示的线程以及相关的副作用

例子 让我们看两个函数,它们的区别仅在于它们连接线程的时间:

int count_A() {
    int counter = 0;
    bool flag(true);
    auto t = std::thread([&]{flag = false;});

    while(flag) {    // infinite loop - flag never synchronized
        ++counter;
    }
    t.join();        // joins thread after loop exits
    return counter;
}
int count_B() {
    int counter = 0;
    bool flag(true);
    auto t = std::thread([&]{flag = false;});

    t.join();       // joins thread before loop, forcing synchronization
    while(flag) {
        ++counter;
    }
    return counter;
}
当在
-O3
优化中使用g++版本8.2编译时,调用
count\u A
会导致无限循环,因为编译器假定
标志
始终为真

另一方面,调用
count_B
只会返回
0
的值。因为
标志的值是在
thread.join()
之后检查的,它的值被重新加载,标志是
false
,所以while循环不会执行


请注意,如果将
标志
更改为
原子布尔
,则
计数A
具有递增计数器的预期行为,直到标志设置为false,并且函数不会进入无限循环(相反,子线程将
标志
设置为false时返回一次)

@J.Antonio-你打算自己回答这篇文章吗?没有,但是在你回答之后,我用一些代码来获得更好的理解,我想这将是对答案的一个很好的补充。我真的很感谢您花时间查找标准中涉及的相应部分this@J.AntonioPerez-NP。我只是觉得我可能在你发帖的时候插队了。对于后人来说,值得一提的是,一个人甚至在发布问题之前都可以自己回答,有一个复选框可以打开“提问”上方的回答面板。谢谢你让我知道!老实说,我不知道标准是怎么说的,我也不觉得我能够提供一个全面的答案。变量是局部变量还是全局变量并不重要,只要它的生命周期足够(如这里所示)。