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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 10:42:02