当我在子线程之间测试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 }
答案 0 :(得分:3)
我试图避开共享变量,因此我使用另一个
thread_create()
函数来执行真实的pthread_create()
。
...因此,您似乎为自己创造了一个更糟糕的问题。至少,我通过传递每个线程指向thread_create()
的局部变量input
的指针来解释你的意图避免共享变量,但是,正如在注释中观察到的那样,指针一旦thread_create()
在启动新线程后立即返回,它就会变为无效。当线程此后取消引用这些指针 - 它们会多次执行 - 它们会产生未定义的行为。
问题1 :为什么返回值不正确?
程序的行为是未定义的,因此返回值可能不是您想要的或期望的,但没有依据来判断它们是否正确。
问题2 :主线程如何等待其他线程完成?(我不确定,所以我使用while(1)来确保所有线程完成。)< / p>
一个线程等待另一个线程完成的方法是调用pthread_join()
。由于每个线程都加入了前一个线程(或者至少尝试这样做),因此只需要主线程加入最后一个线程。实际上,您不能允许两个不同的线程同时尝试加入同一个线程,因此最后一个线程是主线程 尝试加入的唯一线程。
修复不确定性:
摆脱thread_create()
。它只是混淆了这个问题。
您有两种选择:
mix
个对象 - 例如他们的数组 - 并将不同的一个交给每个帖子。mix
对象,将其传递给每个子对象,并让子线程进行内部复制。此备选方案需要主线程和子线程之间的同步,以便主线程在新子项复制之前不会继续。我选择使用数组,因为它更容易正确实现:
// ...
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;
}