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

C多线程问题:循环创建线程时所有线程使用最后一次迭代参数

问题分析与解决方案

问题根源

你在for循环中定义的ThreadArgs myargs是栈上的局部变量,它的内存地址在整个循环过程中是固定的。当调用pthread_create将&myargs传给线程后,线程可能还没来得及执行到ThreadArgs myargs = *args;完成参数拷贝,循环就已经进入下一次迭代,直接覆盖了这个变量里的内容。最终所有线程读取的都是最后一次循环写入的参数值。sleep()能“解决”是因为给了线程足够的时间完成参数拷贝,但这是临时的 workaround,并非正确解法。


解决方案

方案1:动态分配参数内存(推荐,适用于线程数动态的场景)

为每个线程单独分配堆内存存储参数,避免循环覆盖。线程执行完成后记得释放内存,防止泄漏。

修改循环代码:

for(int i = 0; i < NO_OF_THREADS; i++) {
    int ordered_product = (rand() % NO_OF_PRODUCTS);
    int ordered_quantity = (rand() % 10) + 1;
    int customer = (rand() % NO_OF_CUSTOMERS);

    printf("%d %d %d\n", customer+1, ordered_quantity, ordered_product+1);

    // 动态分配参数内存
    ThreadArgs *myargs = malloc(sizeof(ThreadArgs));
    if (myargs == NULL) {
        perror("malloc failed");
        exit(1);
    }
    myargs->customer_id = customer;
    myargs->product_id = ordered_product;
    myargs->product_quantity = ordered_quantity;

    int rc = pthread_create(&mythreads[i], NULL, thread_function, myargs);
    if(rc != 0) {
        perror("Pthread create");
        free(myargs); // 创建失败时释放已分配的内存
        exit(1);
    }
}

修改线程函数:

void* thread_function(void* arg) {
    ThreadArgs* args = (ThreadArgs*) arg;
    int customer_id = args->customer_id + 1;
    int product_quantity = args->product_quantity;
    int product_id = args->product_id + 1;

    printf("Customer %d purchased %d of Product %d\n", customer_id, product_quantity, product_id);

    free(args); // 释放动态分配的内存
    return NULL;
}

方案2:用数组预存所有线程参数(适用于线程数固定的场景)

如果NO_OF_THREADS是编译期确定的常量,可以定义一个数组存储每个线程的参数,每个参数都有独立的内存空间,不会被循环覆盖。

修改代码:

// 循环外定义参数数组,确保内存生命周期覆盖所有线程
ThreadArgs thread_args[NO_OF_THREADS];

for(int i = 0; i < NO_OF_THREADS; i++) {
    int ordered_product = (rand() % NO_OF_PRODUCTS);
    int ordered_quantity = (rand() % 10) + 1;
    int customer = (rand() % NO_OF_CUSTOMERS);

    printf("%d %d %d\n", customer+1, ordered_quantity, ordered_product+1);

    // 填充当前线程的参数
    thread_args[i].customer_id = customer;
    thread_args[i].product_id = ordered_product;
    thread_args[i].product_quantity = ordered_quantity;

    int rc = pthread_create(&mythreads[i], NULL, thread_function, &thread_args[i]);
    if(rc != 0) {
        perror("Pthread create");
        exit(1);
    }
}

线程函数可以保持你的原始实现,因为数组元素的内存不会被循环覆盖,线程可以安全拷贝参数。

方案3:循环内等待线程完成(串行执行,仅适用于调试或低并发场景)

这种方法会让线程逐个执行,失去多线程并行的优势,但实现最简单:

for(int i = 0; i < NO_OF_THREADS; i++) {
    // ... 生成参数、创建线程的代码 ...

    pthread_join(mythreads[i], NULL); // 等待当前线程执行完毕再进入下一次循环
}

内容的提问来源于stack exchange,提问作者MoChahadeh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 03:23:22