C 对PTHREADS过于偏执?

C 对PTHREADS过于偏执?,c,variables,pthreads,local,C,Variables,Pthreads,Local,在我查找的所有地方,我都找到了使用pthreads的教程和示例,该pthreads的指针指向函数调用的参数,该函数调用引用了主函数中的全局变量或局部变量。 另一方面,由于我不能使用全局变量,我有以下代码: pthread_t thread; void *thread_created(void *np); void function2(int numParam); void function1(int numParam) { int cond=0; ... if (co

在我查找的所有地方,我都找到了使用pthreads的教程和示例,该pthreads的指针指向函数调用的参数,该函数调用引用了主函数中的全局变量或局部变量。 另一方面,由于我不能使用全局变量,我有以下代码:

pthread_t thread;

void *thread_created(void *np);
void function2(int numParam);

void function1(int numParam)
{
    int cond=0;
    ...
    if (cond)
        {
            pthread_attr_t attr;
            pthread_attr_init(&attr);
            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
            pthread_create(&thread,&attr,thread_created,&numParam);
        }
}

void *thread_created(void *np)
{
    int numParam;
    numParam=*((int *)np);
    function2(numParam);
    return NULL;
}

void function2(int numParam)
{
}
然而,在我看来,在某些情况下,function1中的局部变量numParam可能在线程有机会获得其值之前超出范围。比赛条件。
因此,我修改了代码,使用全局互斥体和条件变量添加标有//的行是一种非常糟糕的方法。它基本上序列化了所有线程创建操作。有几种更好的方法可以将参数传递给新线程:

  • 最好的方法是:如果您的数据是单个整数,可以通过转换为
    void*
    并返回来忠实地表示,那么就这样做。这不需要任何同步,也不会分割内存。或者,如果您不想假设您可以像这样强制转换
    void*
    ,您可以通过
    const char dummy[N]支持较小范围的整数值
    0
    N
    并将
    dummy+i
    传递给
    pthread\u create
    然后从thread start函数中接收的指针参数中减去
    dummy
    。此变体是100%便携式的,即C标准要求其工作

  • 轻同步:将线程参数放入结构中,并向结构中添加
    sem\t
    成员。将结构放在父线程的堆栈上(自动存储在调用
    pthread\u create
    的函数中)。在创建线程之前让父线程调用
    sem\u init
    ,在
    pthread\u create
    之后返回
    sem\u wait
    。一旦访问完参数(例如,将参数复制到自己的本地存储),新线程将调用
    sem\u post
    ,父线程将调用
    sem\u destroy
    一次
    sem\u wait
    返回。此时,新线程不再使用参数结构,因此父线程可以删除它,让它超出范围,等等

  • 中度同步:
    malloc
    。父线程通过
    malloc
    为参数分配存储,新线程负责调用
    free
    。我认为这种适度的重同步是因为,即使 MalOC/通常尝试使用线程局部ARIENS,当一个线程中分配内存并释放另一个线程时,也会有一个基本的全局同步成本(虽然这个代价可以推迟)。当然,这种方法也有潜在的内存碎片成本,以及处理分配失败路径的复杂性成本


  • 使用R.response,这是最终代码,以防有人需要它:

    pthread_t thread;
    sem_t semaphore;
    
    void initialize_semaphore()
    {
        sem_init(&semaphore,0,1);
    }
    
    void destroy_semaphore()
    {
        sem_destroy(&semaphore);
    }
    
    void *thread_created(void *np);
    void function2(int numParam);
    
    void function1(int numParam)
    {
        int cond=0;
        ...
        if (cond)
            {
                pthread_attr_t attr;
                pthread_attr_init(&attr);
                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
                pthread_create(&thread,&attr,thread_created,&numParam);
                sem_wait(&semaphore);
            }
    }
    
    void *thread_created(void *np)
    {
        int numParam;
        numParam=*((int *)np);
        sem_post(&semaphore);
        function2(numParam);
        return NULL;
    }
    
    void function2(int numParam)
    {
    }
    
    谢谢大家的回答

    问候


    alfredomeraz.

    为什么不在堆上为int添加malloc空间呢?那么,当线程完成时,它会被释放吗?这样,您就不会有在函数返回后访问变量的未定义行为。我考虑过,甚至创建一个结构,添加一个将在线程内更改的标志,向主线程发出值已更改的信号。我想我并没有真正理解您要做的事情。您想修改一个变量,但担心main()会践踏它?如果是这样,你需要一把锁。只要在结构中传递一个锁和一个指向变量的指针,然后每次读或写变量锁的时候都会这样做?@ScottyBauer说什么-不要再乱搞标志和互斥体了,只需要malloc这个该死的参数:)至于malloc的使用,它被丢弃是因为它会造成一种更难调试和克服的情况:在低资源环境中由于大量使用内存分配而导致堆碎片,这是因为低资源本身造成的。至于我提到的flag解决方案:这意味着,将它放入一个空循环,这会在资源不足的环境中占用资源。谢谢你的回答。我有些怀疑,你。如果您的第一个选项在没有竞争条件的意义上是正确的,那么我的第一段代码也是正确的(我仍然怀疑竞争条件的存在)。对于我在其他消息中所写的内容,我放弃您的第三个选项。你的第二个选择是我认为我真正缺少的答案。也许条件变量解决方案是可行的,但这种情况确实需要一个信号量。所以我接受你的回答。非常感谢:-)不。我的第一个选择是按值传递参数。不存在竞争条件,因为不存在任何共享对象。代码正在父线程中传递正在修改(或其生存期即将结束)的对象的地址。那完全不同。哇。。。我明白你的意思。。。“注入”参数的聪明方法。。。从没想过那样做。。。但是你的权利:-)。。。我采取这种方法。。。至少,在可行的地方,比如我现在面对的那个。。。在我的系统中的下一个ocurrances,如果它们不适合这种方法,我仍然有可用的信号量。。。再次非常感谢:-)
    pthread_t thread;
    sem_t semaphore;
    
    void initialize_semaphore()
    {
        sem_init(&semaphore,0,1);
    }
    
    void destroy_semaphore()
    {
        sem_destroy(&semaphore);
    }
    
    void *thread_created(void *np);
    void function2(int numParam);
    
    void function1(int numParam)
    {
        int cond=0;
        ...
        if (cond)
            {
                pthread_attr_t attr;
                pthread_attr_init(&attr);
                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
                pthread_create(&thread,&attr,thread_created,&numParam);
                sem_wait(&semaphore);
            }
    }
    
    void *thread_created(void *np)
    {
        int numParam;
        numParam=*((int *)np);
        sem_post(&semaphore);
        function2(numParam);
        return NULL;
    }
    
    void function2(int numParam)
    {
    }