线程工作函数未接收0参数且pthread_join触发段错误求助
问题分析与解决方案
核心问题根源
- 参数传递的竞态问题:你传递给
pthread_create的是循环变量i的地址,主线程的循环会快速递增i,子线程启动后读取*(int*)arg时,i的值已经被主线程修改,导致多个线程拿到相同的索引值,甚至0索引的线程还没来得及读取i,i就已经变成1,这就是值重复、0索引无法正常工作的直接原因。 - 段错误的触发逻辑:当没有打印语句时,主线程创建线程的速度极快,部分线程可能还未完成初始化就被主线程调用
pthread_join;同时,线程拿到错误的索引值后,会越界访问result.data数组,直接触发段错误。而打印语句会强制线程执行减速,给了子线程足够时间读取正确的i值,避免了越界,所以不会报错。
解决方案
方案1:为每个线程分配独立的参数存储
给每个线程单独分配一个索引变量,避免多个线程共享同一个i的地址:
// 主线程代码修改 pthread_t* threads = (pthread_t*)malloc(mat1->rows * sizeof(pthread_t)); // 分配数组存储每个线程的独立索引 int* thread_args = (int*)malloc(mat1->rows * sizeof(int)); struct timeval start, end; for (int i = 0; i < result.rows; i++) { thread_args[i] = i; // 传递独立索引的地址 pthread_create(&threads[i], NULL, multiplyMatrixRows, (void*)&thread_args[i]); } for (int i = 0; i < result.rows; i++) { pthread_join(threads[i], NULL); } // 记得释放内存 free(thread_args); free(threads);
工作函数无需修改,现在每个线程读取的是独立的thread_args[i],不会被主线程的循环干扰。
方案2:直接传递索引值(更高效)
利用intptr_t类型将整数索引转换为void*传递,无需额外分配内存:
工作函数修改
void* multiplyMatrixRows(void* arg) { // 将指针转换回整数索引 int i = (int)(intptr_t)arg; printf("%d Loop \n", i); for (int j = 0; j < result.cols; j++) { result.data[i][j] = 0; for (int k = 0; k < mat2->rows; k++) { result.data[i][j] += mat1->data[i][k] * mat2->data[k][j]; } //printf("Value of Result: %d \n", result.data[i][j]); } pthread_exit(NULL); }
主线程修改
for (int i = 0; i < result.rows; i++) { // 将整数索引转换为void*类型传递 pthread_create(&threads[i], NULL, multiplyMatrixRows, (void*)(intptr_t)i); }
关于互斥锁的说明
你提到的pthread_mutex_lock在这里是多余的:每个线程负责处理矩阵的独立行,result.data[i][j]的访问完全是线程独有的,不存在多个线程同时修改同一内存地址的情况,因此不需要互斥锁。
内容的提问来源于stack exchange,提问作者Skyler Quinn
相关产品推荐
相关产品推荐

