pthread_create调用异常(跳过/重复)及线程平方和计算问题求助
解决pthread_create异常与线程安全累加问题
看起来你遇到了两个核心问题:一是pthread_create调用出现的异常(有时跳过、有时重复调用),二是全局变量sum累加时的线程安全问题。我来一步步帮你解决。
问题根源分析
- pthread_create参数传递陷阱:如果你的原始代码是在循环中直接传递循环变量的地址(比如
&i)给线程函数,那么线程启动时循环变量可能已经被修改,导致多个线程拿到相同的参数,出现“调用两次”或者“跳过”的假象——本质是线程拿到的任务范围不对。 - 全局变量的竞态条件:多个线程同时对
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
相关产品推荐
相关产品推荐

