c++多线程-线程安全的代码

C++ Multithreading - Thread safe code

本文关键字:代码 安全 线程 多线程 c++      更新时间:2023-10-16

我正在制作一个从.dll运行的游戏引擎。在内部,有一个导出函数,它返回对其中声明的静态类的引用,如下所示:

__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);

问题是:这个代码线程安全吗?

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

我该怎么做才能做到呢?

你的c++版本是什么?如果是c++ 11或更高版本,那么代码是线程安全的。如果在11之前,则第一次调用NF3DGetEngineState是不安全的。

澄清。这并不是说返回对静态变量的引用"不是线程安全的"。相反,它是100%安全的。在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;
}

显然,如果在static变量设置为true之前多次调用此函数,则有可能多次调用constructor。

在c++ 11中,保证永远不会发生这种情况,并且构造函数只被调用一次。