You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 14:36:03