调用线程会在thread.join()之后看到对局部变量的修改吗? [英] Will a calling thread see modifications to local variables after thread.join()?

查看:97
本文介绍了调用线程会在thread.join()之后看到对局部变量的修改吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In the simplest possible example, let's say I have a function that starts a thread, which in turn sets the value of a local variable to true. We join the thread, then leave the function.

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

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

Will this function return true, or is the behavior undefined?

推荐答案

是的,它必须返回true。

Yes, it must return true.


[thread.thread.member]

void join();

4 效果:阻塞直到由 * this表示的线程已完成。

4 Effects: Blocks until the thread represented by *this has completed.

5 同步:由 * this 表示的线程的完成与([[intro.multithread] )对应的成功 join()返回。

5 Synchronization: The completion of the thread represented by *this synchronizes with ([intro.multithread]) the corresponding successful join() return.

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

So the execution of the thread represented by the handle, and associated side effects are done before join returns to the calling context.

让我们看一下两个函数,它们的区别仅在于它们加入线程的时间不同:

Let's look at two functions, which differ only in when they join a thread:

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_A 会导致无限循环,因为编译器认为 flag 始终为真。

When compiled with g++ version 8.2 at -O3 optimization, invoking count_A results in an infinite loop because the compiler assumes flag is always true.

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

On the other hand, invoking count_B will just return a value of 0. Because the value of flag is checked after thread.join(), it's value is re-loaded, and flag is false so the while loop doesn't execute.

请注意,如果 flag 更改为 atomic_bool ,则 count_A 具有增加计数器的预期行为,直到将该标志设置为false,并且函数不会进入无限循环(而是如果子线程将 flag 设置为false,则返回一次。

Note that if flag is changed to an atomic_bool, then count_A has the intended behavior of incrementing the counter until the flag is set to false, and the function does not enter an infinite loop (instead returning once flag is set to false by the child thread).

这篇关于调用线程会在thread.join()之后看到对局部变量的修改吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆