2015-10-23 197 views
2

我正在研究从.dll运行的游戏引擎。里面,有一个导出函数,返回到它声明的静态类的引用,象下面这样:C++多线程 - 线程安全代码

__forceinline __declspec(dllexport) STATE* NF3DGetEngineState(void) 
{ 
    static STATE s_State; 
    return &s_State; 
} 

其中STATE是管理所有组件,并且具有通过临界区访问这些函数的类:

void Set(int val) 
{ 
    EnterCriticalSection(&CriticalSection); 
    ClassMember = val; 
    LeaveCriticalSection(&CriticalSection); 
} 

其中“CriticalSection”是当然初始化的STATE类的CRITICAL_SECTION成员。我使用这些功能的上下文是:

NF3DGetEngineState()->Set(10); 

现在的问题是:此代码线程安全吗?

从我所知道的,返回对静态声明的引用不是线程安全的。

我该怎么做才能做到这一点?

+2

请解释你为什么认为它不是线程安全的 –

+0

我听说,对静态声明的返回引用不是线程安全的吗?我对吗? –

+0

你在用'ClassMember'做什么?您需要在设置时使用相同的资源保护。 – JeffRSon

回答

3

哪个是C++版本?如果它是C++ 11或更高版本,那么代码就像线程安全一样。如果是在11岁以前,首先打电话给NF3DGetEngineState是不安全的。

澄清。

这不是对静态变量的返回引用'不是线程安全的'。相反,它是100%安全的。什么不是线程安全的pre-C++ 11本身就是静态变量初始化。对于第一次对该函数的并发调用,C++ 11之前并未做出任何保证。事实上,如果您第一次同时输入此函数,那么与之合作的所有11之前的C++编译器都会遇到问题。其原因是,当使用静态变量,编译器生成的代码,看起来大约像下面:

static bool static_var_initialized = false; 
if (!static_var_initialized) { 
    new (&static_var) StaticVarType(); // Explicit constructor call 
    static_var_initialized = true; 
} 

显然,在调用构造函数多次的可能性,如果你碰巧静态变量之前多次调用该函数设置为true。

在C++ 11中,保证它永远不会发生,构造函数将只被调用一次。它还保证没有线程会看到未构建的价值。

+0

这就是我一直在寻找的东西。感谢您的急需帮助! :) –