本地静态的线程安全初始化:MSVC

Jam*_*mes 7 c++ thread-safety visual-c++

可能重复:
VC2010是静态init线程安全吗?

我知道gcc和llvm-clang发出代码以线程安全的方式初始化本地静态变量(这允许通过在函数中包装全局静态来逃避静态顺序初始化失败).

然而,这篇msdn博客文章是我在这些情况下可以找到的关于vcc行为的最佳文档,并且声称静态初始化不能是线程安全的,因为本地静态的初始化可以递归地调用相同的作用域.

我不买这个论点 - 如果初始化者依赖于它自己的结果,那显然是编程错误.

因此,鉴于本文来自2004年,gcc和clang可以做到这一点,并且当前的msvc文档是不明确的(声明'分配'到本地静态不是线程安全的,但仅此而已):

在MSVC中,本地静态的初始化现在是线程安全的吗?

如果没有,为什么不呢,因为gcc显然可以这样做,但程序员很难在之后加入.

Mat*_* M. 1

C++0x 标准说:

\n\n

\xc2\xa76.7 声明语句 [stmt.dcl]

\n\n
\n

4/所有具有静态存储持续时间 (3.7.1) 或线程存储持续时间 (3.7.2) 的块作用域变量的零初始化 (8.5) 在任何其他初始化发生之前执行。具有静态存储持续时间的块作用域实体的常量初始化 (3.6.2)(如果适用)在首次进入其块之前执行。\n 允许实现使用 static 或线程执行其他块作用域变量的早期初始化存储持续时间与允许实现在命名空间范围内使用静态或线程存储持续时间静态初始化变量的条件相同(3.6.2)。否则,此类变量将在控制第一次通过其声明时被初始化;这样的变量在初始化完成后就被认为已初始化。

\n\n

如果初始化通过抛出异常退出,则初始化尚未完成,因此下次控制进入声明时将再次尝试。

\n\n

如果在初始化变量时控制同时进入声明,则并发执行应等待初始化完成。88

\n\n

如果在初始化变量时控制以递归方式重新进入声明,则行为未定义。

\n\n

[ 例子:

\n
\n\n
int foo(int i) {\n  static int s = foo(2*i); // recursive call - undefined\n  return i+1;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

\xe2\x80\x94结束示例]

\n\n

88) 实现不得在初始化程序的执行过程中引入任何死锁。

\n
\n\n

正如所料,它已经相当完整了。

\n\n

然而事实是,即使是旧版本的 gcc 也已经遵守了这一点,而且实际上做得更好:在递归初始化的情况下,会抛出异常。

\n\n

最后,关于程序员随后添加它:如果您有类似比较和交换之类的可用功能,并且使用足够小的变量,依靠变量的零初始化来标记其非计算状态,那么您通常可以做到这一点。不过我确实同意,如果它是烘烤的,那就容易得多。

\n\n

我担心我已经停止关注 VC++ 的进展了,所以我不知道它现在在哪里。我唯一的建议是......在装配级别上查找。

\n