【问题标题】:Linux Pthread argumentLinux Pthread 参数
【发布时间】:2012-06-08 12:19:01
【问题描述】:

这是我的代码。很简单。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *func(void *arg)
{
    printf("ID=%d\n", *(int*)arg);
    pthread_exit(NULL);
}

int main()
{
    pthread_t pt[4];
    int i;

    for (i = 0; i < 4; i++)
    {
        int temp = i;
        pthread_create(&pt[i], NULL, func, (void*)&temp);
    }
    sleep(1);
    return 0;
}

我编译了它:

gcc p_test.c -lpthread

我运行它。它打印了2 2 3 3。我又跑了一遍。它打印了2 3 3 2

我的问题是:

为什么23 打印了两次?

为什么不打印1 3 2 0 或任何其他结果?

【问题讨论】:

  • 经典的未定义行为。一个普通的数据对象可能无法在一个线程中访问,而另一个线程正在或可能正在修改它。

标签: c linux pthreads posix


【解决方案1】:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *func(void* arg)
{
printf("ID=%d\n", (int)arg);
pthread_exit(NULL);
return 0;
}

int main()
{
pthread_t pt[4];
int i;

for (i =0 ; i < 4; i++)
{

    pthread_create(&pt[i], NULL, func, (void*)i);
    pthread_join(pt[i],NULL);
}



return 0;

}

【讨论】:

    【解决方案2】:

    您将一个指向临时变量的指针传递给线程创建函数,而这个临时变量在循环块结束时超出了范围。在我看来,编译器正在重用临时地址,因此当线程执行时,它们会看到相同的地址位置。

    如果你这样做:

    int *temp = malloc(sizeof(int));
    *temp = i;
    pthread_create(&pt[i], NULL, func, (void*)temp);
    

    相反,您应该会看到预期的结果。

    在这种情况下,线程函数需要在打印后释放int,以避免内存泄漏。

    此外,更好的做法是pthread_join() 您正在等待的线程,而不仅仅是sleep()ing。

    【讨论】:

    • 虽然一定要确保在某处释放分配的内存(线程退出是一个好地方)以避免明显的内存泄漏。
    • @Philip Kendall - 是的!我刚刚意识到我也应该指出这一点。
    • 这行得通,但是将整数参数转换为void *...
    • 这是 100% 安全的吗?您可以在 funk() 中使用之前释放内存。
    • @fhtuft:这个想法是在 thread 函数中释放内存,而不是在 main 中(尽管我承认目前的措辞有点混乱)。
    【解决方案3】:

    因为它打印 temp,所以所有线程共享内存(TheJuice 解释了为什么 temp 是“共享”的),所以所有线程都“共享” temp。使用 mutex 或将 temp 设为私有变量。 Private Variables in Threads

    或者你可以像这样使用phtread_join

    int main()
    {
        pthread_t pt[4];
        int i;
    
        for (i =0 ; i < 4; i++)
        {
    
          pthread_create(&pt[i], NULL, func, (void*)&i);
          pthread_join(pt[i],NULL);
    
        }
    
        //sleep(1);
        return 0;
    }
    

    【讨论】:

    • 不完全是:这个例子有很大的不同,因为temp 超出了范围。因此,在线程中取消引用它的尝试将调用未定义的行为。
    【解决方案4】:

    这里的主要问题是您获取局部变量 temp 的地址,然后在变量范围之外使用该指针 - 一旦您退出循环的一次迭代,您的指针指向 @ 987654322@ 无效,不能取消引用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-07
      • 1970-01-01
      • 1970-01-01
      • 2011-06-26
      • 1970-01-01
      • 2011-02-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多