在最简单的示例中,假设我有一个启动线程的函数,该线程又将局部变量的值设置为 true。我们加入线程,然后离开函数。
bool func() {
bool b = false;
std::thread t([&]() { b = true; });
t.join();
return b;
}
这个函数会返回 true,还是未定义行为?
最佳答案
是的,它必须返回 true。
[thread.thread.member]
void join();
4 Effects: Blocks until the thread represented by
*this
has completed.5 Synchronization: The completion of the thread represented by
*this
synchronizes with ([intro.multithread]) the corresponding successfuljoin()
return.
所以由句柄表示的线程的执行,以及相关的副作用在 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_A
会导致无限循环,因为编译器假定 flag
始终为真.
另一方面,调用 count_B
只会返回值 0
。因为在thread.join()
之后检查了flag
的值,重新加载了它的值,而flag是false
所以while循环不执行。
请注意,如果 flag
更改为 atomic_bool
,则 count_A
具有递增计数器的预期行为,直到将标志设置为false,函数不会进入无限循环(而是在 flag
被子线程设置为 false 时返回)。
关于c++ - 调用线程会在 thread.join() 之后看到对局部变量的修改吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55932983/