通常,当我尝试初始化静态变量
时class Test2 {
public:
static vector<string> stringList;
private:
static bool __init;
static bool init() {
stringList.push_back("string1");
stringList.push_back("string2");
stringList.push_back("string3");
return true;
}
};
// Implement
vector<string> Test2::stringList;
bool Test2::__init = Test2::init();
虽然初始化应该在main函数之前发生(因此,没有线程可以同时访问init),我关心的是:
我使用的是Windows XP,VC6和VC2008编译器。
答案 0 :(得分:7)
在静态变量初始化期间,以下代码线程是否安全?
这完全取决于您的编译器。标准对多线程一无所知。
有没有更好的方法来静态初始化stringlist,而不是使用单独的静态函数(init)?
首先,你需要删除名称前面的__s(那是两个下划线);任何以__开头的名称都是根据标准保留的。 (在某些情况下,也不允许使用单个下划线 - 最好只是避免在名称上引入下划线)
这完全取决于向量是否需要在运行时更改。如果没有,你可能只是使用内置数组:
static const char *strings[] = {
"string1",
"string2",
"string3"
};
答案 1 :(得分:2)
使用带有双下划线的标识符名称的代码不能被认为是安全的,因为它违反了标准关于为实现保留的名称的规则。对于带有前导下划线后跟大写字母的名称也是如此,但是可以使用以下划线开头的其他名称,只要它们不在全局名称空间中即可。见标准,17.4.3.1.2。这些限制在最新的C ++ 0x最终委员会草案中继续,见17.6.3.3.2。
答案 2 :(得分:2)
本地静态初始化不是线程安全的。见http://blogs.msdn.com/oldnewthing/archive/2004/03/08/85901.aspx。
全局静态初始化通常是线程安全的。您的代码应该可以正常工作。
我通常使用单独的init函数,并使用boost :: call_once来确保它只被调用一次。
boost::once_flag boost_once_flag = BOOST_ONCE_INIT;
boost::call_once(init_static_var, boost_once_flag);
答案 3 :(得分:1)
我回答了一个类似的问题:
LoadLibrary and Static Globals
当谈到DLL时,静态初始化和对DllMain的调用被内部关键部分括起来,因此它们是线程安全的。第二个线程将在加载DLL之前等到第一个线程完成。
简而言之,您的静态初始化是安全的。
答案 4 :(得分:0)
它不是线程安全的,因为几个线程可以同时调用它,并且你将对stringList初始化两次。使用线程同步。
答案 5 :(得分:0)
查看我的快速示例,该示例演示了您的容器不是线程安全的。
#include <boost/thread.hpp>
#include <vector>
#include <string>
class NotThreadSafeContainer {
static std::vector<std::string> strings;
static bool is_initialized;
public:
NotThreadSafeContainer() {
if (!is_initialized) {
is_initialized = true;
strings.push_back("string1");
strings.push_back("string2");
strings.push_back("string3");
strings.push_back("string4");
strings.push_back("string5");
}
}
};
bool NotThreadSafeContainer::is_initialized = false;
std::vector<std::string> NotThreadSafeContainer::strings;
void thread_routine() {
while (true) {
// Wow! A container
NotThreadSafeContainer ts_container;
}
};
void main() {
// Uncomment this to remove thread desync errors
// boost::once_flag once_flag = 0;
// boost::call_once(once_flag, thread_routine);
// Start some threads
boost::thread t1(thread_routine);
boost::thread t2(thread_routine);
boost::thread t3(thread_routine);
NotThreadSafeContainer ts_container;
bool SET_BREAKPOINT_HERE;
}
答案 6 :(得分:0)
如果您需要在主运行之前访问这些字符串,这可能会也可能不会起作用,具体取决于编译器/链接器顺序初始化的方式。
最好是: