C语言pthread多线程按编号输出异常的修改方案咨询
问题原因
你代码的核心问题是所有线程都共享了main函数栈上的循环变量i的同一块内存地址:
pthread_create传入的是&i,也就是同一个变量的指针- 线程创建后不会立刻执行,等线程调度起来执行
foo函数解引用指针的时候,循环变量i的值已经被主线程修改,甚至可能已经走完循环进入join阶段被重置为0,所以会出现所有线程读到同一个值的情况,属于典型的线程间数据竞态问题。
可行修改方案
方案1:用独立数组存储每个线程的ID,传入对应元素的地址
提前创建数组存储每个线程的编号,每个线程传对应下标的地址,避免共享同一个变量:
#include <stdio.h> #include <stdlib.h> #include <pthread.h> void *foo(void *arg){ int myid = *(int*) arg; printf("Hello from thread %d\n", myid); return NULL; } int main(void){ pthread_t tid[4]; int ids[4]; // 单独存储每个线程的编号 int i; for(i=0;i<4;i++){ ids[i] = i; pthread_create(&tid[i], NULL, foo, &ids[i]); // 传每个独立id的地址 } for(i=0;i<4;i++){ pthread_join(tid[i], NULL); } return 0; }
方案2:直接将ID值转为void*传递(无需额外内存空间)
因为int的长度小于等于指针的长度,所以可以直接把整数值强转成void*传递,线程里再转回来,避免传指针带来的共享问题:
#include <stdio.h> #include <stdlib.h> #include <pthread.h> void *foo(void *arg){ int myid = (int)(long long)arg; // 先转long long避免类型截断,再转int printf("Hello from thread %d\n", myid); return NULL; } int main(void){ pthread_t tid[4]; int i; for(i=0;i<4;i++){ pthread_create(&tid[i], NULL, foo, (void*)(long long)i); // 直接传编号值 } for(i=0;i<4;i++){ pthread_join(tid[i], NULL); } return 0; }
两种方案都可以实现预期效果,输出顺序由系统线程调度决定,不保证按编号顺序打印。
内容的提问来源于stack exchange,提问作者mirco vandell
相关产品推荐
相关产品推荐

