C 11-当我将局部变量作为参数传递到线程中时,它是否安全

C++ 11 - Is it safe when I pass a local variable as argument into a thread

本文关键字:线程 安全 是否 参数传递 局部变量      更新时间:2023-10-16

我有这个代码

#include <thread>
typedef struct
{
    int a;
    short b;
}TestStruct;
void TestParamRef(const TestStruct& test)
{
    Sleep(3000); /*Sleep to wait for the caller function end*/
    TestStruct i = test; /*Test if the argument's still ok*/
}
void TestParamPointer(TestStruct* test)
{
    Sleep(4000); /*Sleep to wait for the caller function end*/
    TestStruct i = *test; /*Test if the argument's still ok*/
}
void Test()
{
    TestStruct localTest; /*Local variable should be destroyed after this Test function end*/
    localTest.a = localTest.b = 69;
    std::thread threadRef(TestParamRef, localTest);
    threadRef.detach(); /*Bye bye thread*/
    localTest.a = 6969;
    std::thread threadPointer(TestParamPointer, &localTest);
    threadPointer.detach();/*Bye bye thread*/
    localTest.b = 696969;
}
int WINAPI _tWinMain(HINSTANCE  hInstance,
    HINSTANCE   hPrevInstance,
    LPTSTR      lpCmdLine,
    int     nCmdShow)
{
    Test();
    /*Put break point here*/
    return 0;
}

正如您在代码中看到的那样,我尝试测试如果我将局部变量传递到线程中会发生什么,并且该局部变量在线程使用之前会被破坏。我发现TestParampointer获得了一个有趣的值(也许是因为它现在指向垃圾值),但是TestParamRef仍然获得正确的值。

所以我想知道该线程是否真的将其参数存储在自己的内存中?我认为当我使用'const teststruct&amp;测试',该函数不会复制整个param,而是重复使用该参数(当参数很大时,我会使用它 - 就像SQL表的数据一样)。那么它是如何工作的?当我将局部变量传递到线程中时,它是否安全。

std ::线程将复制或移动您传递给它的任何参数,所以是的,它是安全的。

另一方面,传递原始指针不是线程安全。实际上,将指针传递到分离线程上的本地变量是双重不好的,因为在局部变量脱离范围之前,不能保证该线程已完成(您不使用.join()来阻止。直到线程完成为止)。稍后,当线程开始进行工作时,它可能会或可能没有工作,这可能会导致崩溃。

http://en.cppreference.com/w/cpp/thread/thread/thread

通过值移动或复制线程函数的参数。如果 需要将参考参数传递给线程函数,它具有 要包装(例如使用STD :: Ref或STD :: Cref)。

另外,如果您使用std :: ref包装参考,通常它会变得不安全,因为它可以从原始上下文中访问,因此您将需要提供同步方法(Mutex/lock,线程安全容器或您有什么)。