在 C++11 之前,局部静态变量不是线程安全的。我需要使用某些不可重入函数的结果在性能关键函数中初始化静态变量。
我希望看到一个静态变量初始化,它使用互斥锁或其他同步原语,但对常规静态变量进行一些机会性检查,以减少在很久以前变量已经初始化的典型情况下使用互斥锁。似乎 GCC 为 C++11 实现了类似的东西,如 Static initialization and thread safety 中所述, 但那里列出的代码并不完整,只是汇编。
注意:在 Stack Overflow 上有很多问题询问静态变量初始化是否是原子的,但他们似乎对答案“否”感到满意,而且他们似乎没有显示实际的解决方案(如 C++ Static Initializer - Is it thread safe) .
最佳答案
我在 follow-up 中讨论过这个到问题中引用的博客文章。如果由于某种原因你不能使用 boost::call_once
你的 block 作用域静态是一个指针,POD,或者有一个线程安全的构造函数,你可以编写与 GCC 相同的初始化保护代码发出:
// Define a static local variable once, safely, for MSVC
//
// This macro is necessary because MSVC pre-2013 doesn't
// properly implement C++11 static local initialization.
// It is equivalent to writing something like
//
// static type var = stmt;
//
// in a compliant compiler (e.g. GCC since who knows when)
// States for lock checking
enum { uninitialized = 0, initializing, initialized };
// Preprocessor hackery for anonymous variables
#define PASTE_IMPL(x, y) x ## y
#define PASTE(x, y) PASTE_IMPL(x, y)
#define ANON_VAR(var) PASTE(var, __LINE__)
#define STATIC_DEFINE_ONCE(type, var, stmt) \
static type var; \
static int ANON_VAR(state); \
bool ANON_VAR(cont) = true; \
while (ANON_VAR(cont)) { \
switch (InterlockedCompareExchange(&ANON_VAR(state), \
initializing, uninitialized)) { \
case uninitialized: \
var = stmt; \
InterlockedExchange(&ANON_VAR(state), initialized); \
ANON_VAR(cont) = false; \
break; \
case initializing: \
continue; \
case initialized: \
ANON_VAR(cont) = false; \
break; \
} \
} do { } while (0)
你可以这样使用
void concurrently_accessed() {
STATIC_DEFINE_ONCE(int, local_var, thread_unsafe_initializer());
// ...
}
这种方法利用了静态 block 作用域变量的零初始化,这是 C 语言标准所要求的。在实际编译器和运行时支持到达 MSVC 2014 之前,上面的宏将让您安全地使用“神奇”静态。 .
关于c++ - 如何在C++03中实现线程安全的局部静态变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18911772/