C语言pthread多线程程序输出与预期不符,是什么原因导致的?
问题根本原因
竞态条件:所有线程共享同一个循环变量的地址
你调用pthread_create时传递给线程函数的是main函数中循环变量i的内存地址&i,所有创建的子线程都指向栈上的这同一个变量。而i的值会随循环持续修改,子线程被操作系统调度执行的时机完全不确定:- 子线程开始运行读取值时,循环可能已经将
i修改为更大的数值,甚至整个循环已经执行完毕,此时i的最终值为5(循环终止条件为i<5,退出时i已自增到5),所以会出现大量输出5的情况 - 对共享变量
i的读写没有加同步保护,也会出现读取到中间值、重复值的问题,对应你遇到的重复输出2、3等异常情况
- 子线程开始运行读取值时,循环可能已经将
线程执行顺序无系统保证
就算解决了变量共享的问题,操作系统对线程的调度顺序是随机的,也无法保证输出顺序严格为0 1 2 3 4,除非额外加信号量、条件变量等同步机制。
修复方案
方案1:直接传递数值(演示用,利用指针空间存储整数)
#include <stdio.h> #include <pthread.h> #include <stdint.h> void* printInt(void* ptr) { int val = (int)(intptr_t)ptr; printf("%d\n", val); return NULL; } int main() { pthread_t tid[5]; pthread_attr_t attr; pthread_attr_init(&attr); for(int i=0;i<5;i++) { // 直接把i的数值强转为指针传递,不再传递共享地址 pthread_create(&tid[i], &attr, printInt, (void*)(intptr_t)i); } for(int i=0;i<5;i++) { pthread_join(tid[i], NULL); } return 0; }
方案2:独立分配每个线程的参数空间(更规范的实现)
#include <stdio.h> #include <pthread.h> #include <stdlib.h> void* printInt(void* ptr) { int val = *(int*)ptr; free(ptr); // 释放参数占用的堆内存 printf("%d\n", val); return NULL; } int main() { pthread_t tid[5]; pthread_attr_t attr; pthread_attr_init(&attr); for(int i=0;i<5;i++) { int *p = malloc(sizeof(int)); *p = i; pthread_create(&tid[i], &attr, printInt, p); } for(int i=0;i<5;i++) { pthread_join(tid[i], NULL); } return 0; }
注意:以上方案仅解决取值错误的问题,输出顺序依然可能随机,要严格按顺序输出需要额外增加线程同步逻辑。
内容的提问来源于stack exchange,提问作者illusion4u
相关产品推荐
相关产品推荐

