C++ 静态线程安全和初始化顺序
我在编写的一些代码中遇到了线程问题。 MyStruct在多个线程上构造,这有时会导致程序在staticFunc中崩溃。当代码正在访问一个不安全的变量值(MSVC 2012编译器)时,这让人大吃一惊 我的问题是,解决这个问题的最好方法是什么? 我的第一个想法是一起删除静态声明。 这实际上允许我编写的单元测试通过C++ 静态线程安全和初始化顺序,c++,multithreading,constructor,initialization,C++,Multithreading,Constructor,Initialization,我在编写的一些代码中遇到了线程问题。 MyStruct在多个线程上构造,这有时会导致程序在staticFunc中崩溃。当代码正在访问一个不安全的变量值(MSVC 2012编译器)时,这让人大吃一惊 我的问题是,解决这个问题的最好方法是什么? 我的第一个想法是一起删除静态声明。 这实际上允许我编写的单元测试通过 struct MyStruct : baseClass { MyStruct() : baseClass(myFunc()) { } int* myFun
struct MyStruct : baseClass
{
MyStruct() : baseClass(myFunc())
{
}
int* myFunc()
{
this->value = get_array();
// Do some complex stuff to value.
return &this->value[0];
}
int value[const_size];
};
但我担心的是,如果在构造/初始化之前使用值,这不是未定义的行为吗
施工顺序:
编辑:我使用的是MSVC 2012(静态不是线程安全的),不允许移动到其他编译器 第一个问题是您是想在不同的线程之间共享值,还是每个线程都可以存储自己的值 如果要跨线程共享该值,则需要使用关键部分保护所有访问
如果您对持有不同值的不同线程没有问题,则需要查看线程本地存储。c++11为此提供了线程_local,但我不确定MSVC是否支持此功能。否则,您可以使用TlsAlloc、TlsGetValue、TlsSetValue和TlsFree。使用
std::call\u一次
,它就是为了解决这个问题而发明的。从内存中,文件范围静态不需要线程安全静态,因为它们必须在输入main
之前初始化,所以在初始化之前,代码中不可能有任何线程
// Place the func_flag at file scope.
static std::once_flag my_func_flag;
class blah {
static const int* myFunc()
{
static int value[const_size];
std::call_once(my_func_flag, [] {
// perform ALL mutations of value in here.
value = get_array();
});
// Read-only from here on.
return &value[0];
}
};
在
c++11
中,静态也意味着线程安全性,因此一种解决方案是只使用c++11
compiler@bolov还可以将“Dosomecomplementstuff to value”移到一个用于初始化静态变量的函数中。@MikeSeymour是的,我错过了。to OP:原因是静态变量的初始化是线程安全的。如果你初始化然后分配,你就失去了保证。我编辑了我的帖子。我正在使用MSVC 2012,因此静态不是线程安全的。我也没有切换编译器的选项。基类ctor如何调用派生类的方法(在本例中为MyStruct)
// Place the func_flag at file scope.
static std::once_flag my_func_flag;
class blah {
static const int* myFunc()
{
static int value[const_size];
std::call_once(my_func_flag, [] {
// perform ALL mutations of value in here.
value = get_array();
});
// Read-only from here on.
return &value[0];
}
};