Pthread_join()在C中返回不正确的值

时间:2017-06-02 20:11:22

标签: c multithreading synchronization pthreads

当我在子线程之间测试pthread_join()时,我在使用Pthreads时遇到了问题。我试图避免共享变量,所以我使用另一个 thread_create()函数来执行真正的 pthread_create()

为了跟踪线程,我创建了一个pthread_t数组 tid [N] 来存储线程,并且还根据数组中的索引将索引附加到每个线程。

但是,输出显示某些线程具有相同的索引。 我想必须以某种方式共享变量索引。索引作为实际参数传输到thread_create()中,并且在thread_create()函数完成后应该清除struct变量 input 。我不太明白为什么索引在子线程之间共享。 有没有人可以解释这个?在此先感谢!!

总结

问题1:为什么返回值不正确?

问题2:主线程如何等待其他线程完成?(我不确定,所以我使用while(1)来确保所有线程完成。)< / p>

一个注释:如果我们在第38行取消注释sleep(),程序会给出正确的输出。

以下是代码:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <pthread.h>
  4 #include <syscall.h>
  5 
  6 #define N 4
  7 
  8 typedef struct{
  9 
 10         int index;
 11         pthread_t *tid;
 12 
 13 }mix;
 14 
 15 void* thread_talk(mix* input)
 16 { 
 17         int* ret;
 18         int index = input->index;
 19         printf("In process %d, thread %u running, my index is %d\n",
 20               getpid(), pthread_self(), index);
 21               
 22         /*thread 0 won't join*/
 23         if(input->index == 0){
 24                 printf("thread 0 will stop\n");
 25                 return (void*)0;
 26         }
 27         /*Join the thread based on the index of tid*/
 28         pthread_join(input->tid[index - 1], &ret);
 29         printf("My index is %d, I receive the return value %d\n",index, ret);
 30         return (void*)(input->index);
 31 }
 32 
 33 int thread_create(pthread_t* tid, int index)
 34 {
 35         mix input = {index, tid};
 36         printf("my index is %d\n");
 37         pthread_create(&tid[index], NULL, thread_talk, (void*)(&input));
 38         //sleep(1);
 39         return 0;
 40 }
 41 
 42 int main()
 43 {
 44 
 45         pthread_t       tid[N];
 46         int             i;
 47         for(i = 0; i < N; i++)
 48                 thread_create(tid,i);
 49         while(1);       
 50         return 0;
 51 }

1 个答案:

答案 0 :(得分:3)

  

我试图避开共享变量,因此我使用另一个thread_create()函数来执行真实的pthread_create()

...因此,您似乎为自己创造了一个更糟糕的问题。至少,我通过传递每个线程指向thread_create()的局部变量input的指针来解释你的意图避免共享变量,但是,正如在注释中观察到的那样,指针一旦thread_create()在启动新线程后立即返回,它就会变为无效。当线程此后取消引用这些指针 - 它们会多次执行 - 它们会产生未定义的行为。

  

问题1 :为什么返回值不正确?

程序的行为是未定义的,因此返回值可能不是您想要的或期望的,但没有依据来判断它们是否正确

  

问题2 :主线程如何等待其他线程完成?(我不确定,所以我使用while(1)来确保所有线程完成。)< / p>

一个线程等待另一个线程完成的方法是调用pthread_join()。由于每个线程都加入了前一个线程(或者至少尝试这样做),因此只需要主线程加入最后一个线程。实际上,您不能允许两个不同的线程同时尝试加入同一个线程,因此最后一个线程是主线程 尝试加入的唯一线程。

修复不确定性:

  1. 摆脱thread_create()。它只是混淆了这个问题。

  2. 您有两种选择:

    1. 在主线程中创建多个mix个对象 - 例如他们的数组 - 并将不同的一个交给每个帖子。
    2. 在主线程中使用一个mix对象,将其传递给每个子对象,并让子线程进行内部复制。此备选方案需要主线程和子线程之间的同步,以便主线程在新子项复制之前不会继续。
  3. 我选择使用数组,因为它更容易正确实现:

    // ...
    
    int main() {
        pthread_t       tid[N];
        mix             input[N];
        int             i;
    
        for (i = 0; i < N; i++) {
            input[i].index = i;
            input[i].tid = tid;
            pthread_create(&tid[index], NULL, thread_talk, (void*)(input + i));
        }
    
        pthread_join(tid[N - 1], NULL);
    
        return 0;
    }