C++中全局变量的初始化是否会在多线程中进行?
全局变量多线程初始化的疑问与测试
在Bjarne Stroustrup所著《C++ Programming Language》第四版的15.4.2节中,有如下内容:
考虑以下代码:
int x = 3; int y = sqrt(++x);x和y的值可能是什么?直观答案是“3和2!”。原因是:用常量表达式初始化的静态分配对象在链接时完成初始化,所以x变为3。但y的初始化器不是常量表达式(sqrt()不是constexpr),因此y要到运行时才初始化。不过单个翻译单元中静态分配对象的初始化顺序是明确的:按定义顺序初始化(§15.4.1),所以y变为2。
上述推论的漏洞在于:如果使用多线程(§5.3.1、§42.2),每个线程都会执行运行时初始化,且没有隐式提供互斥机制来防止数据竞争。那么一个线程中的sqrt(++x)可能在另一个线程完成x自增之前或之后执行,因此y的值可能是sqrt(4)或sqrt(5)。
疑问
- 实际开发中,多线程初始化全局变量的场景具体是怎样的?
- 如果在
main()函数前声明全局std::thread变量并启动线程,会不会影响其他全局变量的初始化?
测试代码
#include <iostream> #include <thread> using namespace std; extern int x; extern double y; struct Foo { Foo() { cout << "Foo::Foo()" << '\n'; } }; void threadFunc() { cout << "x = " << x << '\n'; cout << "y = " << y << '\n'; } thread t{threadFunc}; int x = 3; double y = sqrt(double(++x)); Foo z; int main() { cout << "x = " << x << '\n'; cout << "y = " << y << '\n'; t.join(); return 0; }
测试结果
使用MSVC 17.5.2版本多次运行该程序,结果始终一致:y的值为2,Foo的构造函数仅被调用一次。
内容的提问来源于stack exchange,提问作者bobeff
相关产品推荐
相关产品推荐

