C++ 多线程 - 线程安全代码

标签 c++ multithreading static thread-safety critical-section

我正在开发一个从 .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;
}

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

在C++11中,可以保证这种情况永远不会发生,并且构造函数只会被调用一次。它还保证没有线程会看到未构造的值。

关于C++ 多线程 - 线程安全代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33302174/

相关文章:

c++ - 为什么使用 (t1-t2)>(1U<<31) 而不是纯粹的比较?

c++: 模板容器,operator[] 没有按预期工作

c++ - C++ win32 中的 WM_COMMAND 捕捉按钮按下

C++ 静态变量。不编译

java - Java中的继承和静态成员

C++理解cocos2d-x函数指针的使用

c++ - 使用 pthread 同时 push() 到共享队列?

android - 每 10 秒后使用 Handler 在 Thread 中调用方法的最简单方法

java - 在决定使用 volatile 时,实际的锁是否重要?

java - main 方法调用非静态方法