可能重复:
VC2010的静态初始化线程安全吗?
我知道gcc和llvm clang发出代码以线程安全的方式初始化局部静态变量(这允许通过在函数中封装全局静态来避免静态顺序初始化的失败(。
然而,这篇msdn博客文章是我能找到的关于vcc在这种情况下的行为的最好的文档,它声称静态初始化永远不可能是线程安全的,因为本地静态的初始化程序可以递归地调用相同的范围。
我不相信这个论点——如果初始化程序依赖于它自己的结果,这显然是一个编程错误。
因此,考虑到这篇文章来自2004年,gcc和clang可以做到这一点,并且当前的msvc文档是不明确的(声明"分配"给本地静态不是线程安全的,但仅此而已(:
本地静态的初始化现在在MSVC中是线程安全的吗
如果没有,为什么不呢,因为gcc显然可以做到这一点,但程序员很难在之后添加
C++0x标准说:
§6.7声明声明[stmt.dcl]
4/具有静态存储持续时间(3.7.1(或线程存储持续时间的所有块范围变量的零初始化(8.5(在进行任何其他初始化之前执行。具有静态存储持续时间的块范围实体的常量初始化(3.6.2((如果适用(在首次输入其块之前执行。允许实现在与允许实现在命名空间范围(3.6.2(中静态初始化具有静态或线程存储持续时间的变量相同的条件下,以静态或线程保存持续时间对其他块范围变量执行早期初始化。否则,在控件第一次通过其声明时初始化此类变量;这样的变量在其初始化完成时被认为是初始化的。
如果初始化通过抛出异常退出,则初始化未完成,因此下次控件进入声明时将重试。
如果在初始化变量时控件同时进入声明,则并发执行应等待初始化完成88
如果控件在初始化变量时递归地重新输入声明,则行为是未定义的。
[示例:
int foo(int i) {
static int s = foo(2*i); // recursive call - undefined
return i+1;
}
-结束示例]
88(实现不能在初始化器的执行过程中引入任何死锁
不出所料,它相当完整。
然而,事实是,即使是较旧版本的gcc也已经遵守了这一点,而且实际上做得更好:在递归初始化的情况下,会抛出异常。
最后,关于程序员在之后添加它:如果有Compare And Swap之类的东西可用,并且使用一个足够小的变量,依靠变量的零初始化来标记其非计算状态,那么通常可以这样做。然而,我确实同意,如果在里面烤会容易得多。
恐怕我已经不再关注VC++的进展了,所以我不知道它现在在哪里。我唯一的建议是…在组装级别查找。
我听说它已经在vs2010中实现了,但找不到任何参考。无论如何,在c++0x标准中,明确要求这样的初始化是线程安全的,所以我想ms迟早会遵守。