传递导致竞争条件的线程参数的方法?

时间:2015-03-24 03:16:07

标签: c multithreading

我对我正在编写的程序有疑问,需要一些多线程。线程函数需要几个参数,我通过执行以下操作来传递这些参数:

  1. 为参数定义了一个结构(让我们称之为ThreadDataStruct)
  2. 初始化此结构并填充值(调用我们的ThreadDataStruct实例THREAD_DATA)
  3. 通过将lpParameter设置为指向struct(& THREAD_DATA)的指针
  4. ,在CreateThread期间将值传递给我的线程
  5. 在线程函数
  6. 中将LPVOID重新转换为ThreadDataStruct

    问题是我创建线程的函数在调用CreateThread后直接返回。我的问题是:创建线程后可以很快返回导致线程无法获取其参数?如果结构是在函数中创建的,然后函数返回,那么如果线程函数的参数不能足够快,那么它的参数会被破坏吗?

    这是一些显示我的意思的POC:

    我们结构的定义:

    typedef struct ThreadDataStruct
    {
    
        int Number;
    };
    

    我们在里面运行的功能:

    void Function()
    {
    
        ThreadDataStruct THREAD_DATA;
        THREAD_DATA.Number = 1;
    
        CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunction, &THREAD_DATA, 0, NULL);
        return;
    }
    

    我们的线程功能:

    void ThreadFunction(LPVOID lpParam)
    {
    
        ThreadDataStruct THREAD_DATA = *(ThreadDataStruct *)lpParam;
        int NumberFromStruct = THREAD_DATA.Number;
    
        return;
    }
    

    我是否需要找到另一种安全传递参数的方法?

1 个答案:

答案 0 :(得分:0)

将评论转移到答案中。

是的,你有竞争条件;是的,你需要有一种不同的方式将参数安全地传递给函数。传递给线程函数的变量(通常)通过地址传递,因此只要线程需要访问它,它就需要持续。在你的代码中,函数返回,这意味着变量不再有效,所以所有的地狱都会破裂。

  

感谢你清理它。有什么方法可以安全地传递参数?我想我可以在Sleep(5000)之后加CreateThread(),但这显然不是最好的方法。

一个选项是让Function()等待线程在返回之前完成。另一个选择是让Function()等待信号量,ThreadFunction()会在信号量读完控制数据时发出信号。

另一种选择,可能是最好的选择,是让调用Function()的函数在可以使用的ThreadDataStruct *中传递,并让它保持这种状态直到所有线程都终止。因此,如果main()调用Function(),那么main()可能会有一个ThreadDataStruct thread_params[32];数组,并且可以将&thread_params[i]传递给i th 调用Function()(可能在循环内)。

void Function(ThreadDataStruct *THREAD_DATA)
{
    THREAD_DATA->Number = 1;

    CreateThread(NULL, 0, ThreadFunction, THREAD_DATA, 0, NULL);
}

int main(void)
{
    ThreadDataStruct thread_params[32];

    for (int i = 0; i < 32; i++)
        Function(&thread_params[i]);

    …code to wait for threads to exit…
}

Function()中的更改包括:

  • 添加参数。
  • 通过指针初始化参数。
  • 直接传递参数,而不是&THREAD_DATA
  • 不要转换线程函数指针类型;确保ThreadFunction() CreateThread()调用return;是正确的类型。
  • void函数末尾的{{1}}没有任何美德。

毫无疑问,还有其他同等技术可用;这些立即浮现在脑海中。但是,通常情况下,控制代码具有某种可用的数据结构数组,并将数组的一个元素传递给每个线程启动函数的调用。