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

pthread_create调用异常(跳过/重复)及线程平方和计算问题求助

解决pthread_create异常与线程安全累加问题

看起来你遇到了两个核心问题:一是pthread_create调用出现的异常(有时跳过、有时重复调用),二是全局变量sum累加时的线程安全问题。我来一步步帮你解决。

问题根源分析

  1. pthread_create参数传递陷阱:如果你的原始代码是在循环中直接传递循环变量的地址(比如&i)给线程函数,那么线程启动时循环变量可能已经被修改,导致多个线程拿到相同的参数,出现“调用两次”或者“跳过”的假象——本质是线程拿到的任务范围不对。
  2. 全局变量的竞态条件:多个线程同时对sum做累加操作,这是典型的非原子操作,会导致数据覆盖,最终结果错误。

修正后的完整代码

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>

#define THREAD_COUNT 10
#define NUM_PER_THREAD 10

// 全局数组和累加结果
int nums[100];
long long sum = 0;
// 互斥锁,保护sum的修改
pthread_mutex_t sum_mutex;

// 线程参数结构体,传递每个线程要处理的数字范围
typedef struct {
    int start;
    int end;
} ThreadArgs;

// 线程函数:计算指定范围数字的平方和,累加到sum
void* calculate_square_sum(void* arg) {
    ThreadArgs* args = (ThreadArgs*)arg;
    long long local_sum = 0; // 先计算局部和,减少锁的竞争

    for (int i = args->start; i <= args->end; i++) {
        local_sum += (long long)nums[i-1] * nums[i-1]; // nums是0索引,数字是1-100
    }

    // 加锁修改全局sum
    pthread_mutex_lock(&sum_mutex);
    sum += local_sum;
    pthread_mutex_unlock(&sum_mutex);

    // 释放参数内存
    free(arg);
    pthread_exit(NULL);
}

int main() {
    // 初始化全局数组
    for (int i = 0; i < 100; i++) {
        nums[i] = i + 1;
    }

    // 初始化互斥锁
    if (pthread_mutex_init(&sum_mutex, NULL) != 0) {
        perror("Mutex initialization failed");
        return 1;
    }

    pthread_t threads[THREAD_COUNT];

    for (int i = 0; i < THREAD_COUNT; i++) {
        // 为每个线程分配参数结构体,避免循环变量地址被覆盖
        ThreadArgs* args = (ThreadArgs*)malloc(sizeof(ThreadArgs));
        if (args == NULL) {
            perror("Malloc failed");
            return 1;
        }
        args->start = i * NUM_PER_THREAD + 1;
        args->end = (i + 1) * NUM_PER_THREAD;

        // 创建线程,检查返回值确保成功
        int ret = pthread_create(&threads[i], NULL, calculate_square_sum, (void*)args);
        if (ret != 0) {
            printf("Failed to create thread %d: %d\n", i, ret);
            free(args); // 失败时释放已分配的内存
            return 1;
        }
    }

    // 等待所有线程完成
    for (int i = 0; i < THREAD_COUNT; i++) {
        pthread_join(threads[i], NULL);
    }

    // 销毁互斥锁
    pthread_mutex_destroy(&sum_mutex);

    printf("Total sum of squares: %lld\n", sum);
    return 0;
}

关键修改点说明

  • 线程参数传递:用ThreadArgs结构体为每个线程单独分配参数内存,避免了循环变量地址被覆盖的问题——每个线程拿到的都是独立的、正确的任务范围。
  • 互斥锁保护全局sum:使用pthread_mutex_t对sum的修改加锁,确保同一时间只有一个线程能修改sum,解决了竞态条件。
  • 局部累加优化:先在线程内部计算局部平方和,再一次性加到全局sum,减少了锁的持有时间,提升性能。
  • 错误检查:对pthread_create、malloc、pthread_mutex_init的返回值做检查,避免隐性错误。
  • 资源清理:线程结束后释放参数内存,主线程等待所有线程完成后销毁互斥锁,避免内存泄漏。

编译与运行

用以下命令编译(需要链接pthread库):

gcc -o square_sum square_sum.c -lpthread
./square_sum

正确结果应该是1^2 + 2^2 + ... + 100^2 = 338350,你可以验证这个结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:39:43