我正在解决这个问题:从命令行获取一个字母和相同文件的名称,计算每个文件中字符的出现次数,每个文件使用一个线程,然后打印总出现次数。
这是我的代码:
typedef struct _CharFile{
char c;
char *fileName;
} CharFile;
pthread_mutex_t count = PTHREAD_MUTEX_INITIALIZER;
int sum = 0;
void *CountFile(void *threadarg);
int main(int argc, const char * argv[]) {
pthread_t threads[argc-2];
int chck, t;
CharFile cf;
for ( t=0 ; t<argc-2 ; t++ ){
cf.c = argv[1][0];
cf.fileName = (char *)argv[t + 2];
chck = pthread_create(&threads[t], NULL, CountFile, (void *) &cf);
if (chck){
printf("ERROR; return code from pthread_create() is %d\n", chck);
exit(-1);
}
}
printf("%lld occurrences of the letter %c in %lld threads\n", (long long)sum, argv[1][0], (long long)argc-2);
return 0;
}
void *CountFile(void *threadarg){
FILE *in;
CharFile *cf;
char c;
int counter = 0;
cf = (CharFile *) threadarg;
in = fopen(cf->fileName, "r");
if (in == NULL){
perror("Error opening the file!\n");
pthread_exit(NULL);
}
while (fscanf(in, "%c", &c) != EOF){
if(c == cf->c){
counter += 1;
}
}
fclose(in);
pthread_mutex_lock(&count);
sum += counter;
pthread_mutex_unlock(&count);
pthread_exit(NULL);
}
我在文件打开或线程创建中没有收到任何错误,但我的输出总出现次数始终为 0。我还尝试在线程中打印计数器,即使我的输入文件不同,每次在所有线程中都会得到相同的数字。我是否错误地使用了互斥锁,或者还有其他问题吗?
这是我的输出之一:
61 occurrences of e in this thread
0 occurrences of the letter e in 3 threads
61 occurrences of e in this thread
61 occurrences of e in this thread
Program ended with exit code: 9
最佳答案
这里存在几个线程问题。
1) 主线程将继续与新生成的线程异步。根据代码,主线程很可能会在 CountFile 线程完成之前完成并退出。在 Linux 上,当主线程返回时,C 运行时将执行 exit_group 系统调用,该调用将终止所有线程。
您需要添加一些检查以确保 CountFile 线程已完成相关工作部分。在此示例中,查看在主线程中使用 pthread_join()。
2) 主线程中的“cf”存储是一个堆栈局部变量,通过指针传递给每个线程。但是,由于是相同的存储,因此可能会发生多种类型的故障。 a) 当工作线程访问工作单元时,主线程可以更新工作单元。 b) 相同的工作单元被发送到多个/所有线程。
您可以通过多种方式解决此问题:“cf”可以是每个线程的 CharFile 数组。或者可以为每个线程动态分配“cf”。前者的性能和内存效率更高一些,但后者在结构上可能更好。特别是该主线程将其本地堆栈空间中的地址提供给另一个线程。
3) 一旦第 1 项被解决并且线程在主线程 printf 之前退出,互斥锁的使用就可以了。但无论如何,最好将 pthread_mutex_locks 放在“sum”的主线程访问周围。给定此代码可能没有必要,但 future 的代码重构可能会改变这一点。
关于使用线程和互斥体计算文件中的字符数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46576148/