多线程处理文本整数质数筛选:线程重复执行问题求助
多线程处理多文件质数筛选出现重复写入与执行异常问题
我需要通过多线程从3个文本文件读取整数值,判断质数后写入新文件。功能函数本身能正常工作,但线程创建的循环逻辑有问题,导致线程重复执行、执行次数异常,程序持续写入重复值,无法正确完成1159999个数值的处理与存储。
现有代码如下:
#include <stdlib.h> #include <pthread.h> #include <stdio.h> #include <string.h> pthread_mutex_t lck; typedef struct{ int start; int end; }Innerstruct; struct data{ FILE **fptr; Innerstruct *inner; int numberthreads; int totalno; }; int primecount=0;//to store prime numbers count int nofiles=3; void countlines(int *count,FILE **fptr,int nofiles){ //counts the no of lines of cordinates from the text file int i; *count = 0; for(i=0;i<nofiles;i++){ fseek(fptr[i], 0, SEEK_SET); char line[256]; // buffer to store each line while(fgets(line, sizeof(line), fptr[i])){ if(strlen(line) > 1){ // only increment if line is not empty so that this doesn't count blank spaces (*count)++; } } } } void *getstorecountprime(void *p){ FILE *fptr4; fptr4 = fopen("PrimeNumber.txt","w"); if(fptr4==NULL){ printf("Error creating file"); } struct data *d1 = p; int i,j,k,num,start,end; for(k=0;k<d1->numberthreads;k++){ start= d1->inner[k].start; end = d1->inner[k].end; for(j=start;j<=end;j++){ for(i=0;i<nofiles;i++){ fseek(d1->fptr[i], j, SEEK_SET); fscanf(d1->fptr[i],"%d",&num); if(checkprime(num)){ pthread_mutex_lock(&lck); fprintf(fptr4,"%d\n",num); primecount++; pthread_mutex_unlock(&lck); } } } } } void main(){ //checking for any error on opening the files FILE *fptr1,*fptr2,*fptr3; // opening text files fptr1 = fopen("PrimeData1.txt","r"); fptr2 = fopen("PrimeData2.txt","r"); fptr3 = fopen("PrimeData3.txt","r"); if(fptr1==NULL || fptr2==NULL || fptr3==NULL){ printf("Could not open all files"); exit(1); } pthread_mutex_init(&lck,NULL); FILE *fptr[] = {fptr1,fptr2,fptr3}; //array of file pointer int num_threads,sliceperthread,*numarray; int i; int totalcount = 0;//to store total numbers pthread_t *id; struct data d1; countlines(&totalcount,fptr,nofiles);//counts the no of lines from txt files numarray = malloc(totalcount*sizeof(int));//dma to store all datas in array printf("Enter how many threads do you want:"); scanf("%d",&num_threads); id = malloc(num_threads*sizeof(pthread_t));//dma thread equal to the number of thread d1.inner = malloc(num_threads*sizeof(Innerstruct));//dma the inner structure containing start and end d1.fptr = malloc(nofiles*sizeof(FILE*));//dma the fptr as array of nofiles size sliceperthread = totalcount/num_threads; d1.fptr=fptr;//assigned the fptr of structure to array of file pointer created above d1.numberthreads=num_threads; d1.totalno = totalcount; d1.inner[0].start = 0; d1.inner[0].end = sliceperthread; for(i=1;i<=num_threads;i++){ d1.inner[i].start = d1.inner[i-1].end + 1; d1.inner[i].end = d1.inner[i-1].end + sliceperthread; } for(i=0;i<num_threads;i++){ pthread_create(&id[i],NULL,getstorecountprime,&d1); pthread_join(id[i],NULL); } printf("%d",primecount); } int checkprime(int n){ int i; for(i=2;i<=n/2;i++){ if(n%i == 0){ return 0; }else{ return 1; } } }
核心问题梳理
- 线程任务重复执行:每个线程都遍历所有线程的任务区间(
for(k=0;k<d1->numberthreads;k++)),导致所有线程重复处理全部数据,这是重复写入的核心原因。 - 文件打开模式错误:每个线程用
"w"模式打开输出文件,会清空之前的内容,多线程同时打开还会引发竞态问题。 - 文件定位逻辑错误:
fseek按字节偏移,而非行偏移,用行数j定位会读取到错误数值。 - 线程串行执行:创建线程后立即
pthread_join,导致线程无法并行,失去多线程意义。 - 质数判断逻辑失效:
checkprime第一次循环就返回结果,比如n=9会被误判为质数。 - 数组越界访问:任务区间循环
for(i=1;i<=num_threads;i++)会访问超出分配范围的数组元素。 - 内存泄漏:多处
malloc的内存未释放,文件未关闭。
修复后的代码
#include <stdlib.h> #include <pthread.h> #include <stdio.h> #include <string.h> #include <math.h> pthread_mutex_t lck; int primecount = 0; int nofiles = 3; // 单线程任务参数结构体 typedef struct { int *numarray; int start_line; int end_line; FILE *out_fptr; } ThreadData; // 统计所有文件的总行数 void count_total_lines(int *totalcount, FILE **fptr) { *totalcount = 0; char line[256]; for (int i = 0; i < nofiles; i++) { fseek(fptr[i], 0, SEEK_SET); while (fgets(line, sizeof(line), fptr[i])) { if (strlen(line) > 1) (*totalcount)++; } } } // 加载所有文件的数值到数组 void load_numbers_to_array(int *numarray, FILE **fptr) { int idx = 0; char line[256]; for (int i = 0; i < nofiles; i++) { fseek(fptr[i], 0, SEEK_SET); while (fgets(line, sizeof(line), fptr[i])) { if (strlen(line) > 1) { sscanf(line, "%d", &numarray[idx++]); } } } } // 修正后的质数判断函数 int checkprime(int n) { if (n <= 1) return 0; if (n == 2) return 1; if (n % 2 == 0) return 0; for (int i = 3; i <= sqrt(n); i += 2) { if (n % i == 0) return 0; } return 1; } // 线程处理函数:仅处理分配给自己的区间 void *process_prime(void *arg) { ThreadData *data = (ThreadData *)arg; int num; for (int j = data->start_line; j < data->end_line; j++) { num = data->numarray[j]; if (checkprime(num)) { pthread_mutex_lock(&lck); fprintf(data->out_fptr, "%d\n", num); primecount++; pthread_mutex_unlock(&lck); } } pthread_exit(NULL); } int main() { // 打开输入文件 FILE *fptr1 = fopen("PrimeData1.txt", "r"); FILE *fptr2 = fopen("PrimeData2.txt", "r"); FILE *fptr3 = fopen("PrimeData3.txt", "r"); if (!fptr1 || !fptr2 || !fptr3) { printf("Could not open all files\n"); exit(1); } FILE *fptr[] = {fptr1, fptr2, fptr3}; pthread_mutex_init(&lck, NULL); int totalcount = 0; count_total_lines(&totalcount, fptr); // 加载所有数值到数组,避免线程中重复操作文件 int *numarray = malloc(totalcount * sizeof(int)); if (!numarray) { printf("Malloc failed for numarray\n"); exit(1); } load_numbers_to_array(numarray, fptr); // 获取线程数量 int num_threads; printf("Enter how many threads do you want: "); scanf("%d", &num_threads); // 分配线程和任务参数内存 pthread_t *threads = malloc(num_threads * sizeof(pthread_t)); ThreadData *thread_datas = malloc(num_threads * sizeof(ThreadData)); if (!threads || !thread_datas) { printf("Malloc failed for threads/thread_datas\n"); exit(1); } // 主线程打开输出文件,统一传递给所有线程 FILE *out_fptr = fopen("PrimeNumber.txt", "w"); if (!out_fptr) { printf("Error creating output file\n"); exit(1); } // 分配每个线程的处理区间 int slice = totalcount / num_threads; for (int i = 0; i < num_threads; i++) { thread_datas[i].numarray = numarray; thread_datas[i].start_line = i * slice; // 最后一个线程处理剩余所有数据,避免遗漏 thread_datas[i].end_line = (i == num_threads - 1) ? totalcount : (i + 1) * slice; thread_datas[i].out_fptr = out_fptr; pthread_create(&threads[i], NULL, process_prime, &thread_datas[i]); } // 等待所有线程执行完成 for (int i = 0; i < num_threads; i++) { pthread_join(threads[i], NULL); } printf("Total primes found: %d\n", primecount); // 释放所有资源 fclose(fptr1); fclose(fptr2); fclose(fptr3); fclose(out_fptr); free(numarray); free(threads); free(thread_datas); pthread_mutex_destroy(&lck); return 0; }
关键修复说明
- 任务拆分优化:每个线程仅处理分配给自己的区间,避免重复处理数据。
- 数据预加载:先将所有文件的数值读取到数组,线程直接从数组读取,解决文件定位错误问题,提升效率。
- 质数判断修正:修复判断逻辑,正确识别质数。
- 输出文件单例化:主线程统一打开输出文件,传递给所有线程,避免多线程重复打开清空文件。
- 并行执行实现:先创建所有线程,再统一等待完成,真正实现多线程并行处理。
- 边界处理修正:最后一个线程处理剩余所有数据,避免遗漏;修正数组访问边界,防止越界。
- 资源清理:添加所有内存释放、文件关闭、互斥锁销毁操作,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Yuyish
相关产品推荐
相关产品推荐

