使用线程和互斥体计算文件中的字符数

标签 c multithreading mutex

我正在解决这个问题:从命令行获取一个字母和相同文件的名称,计算每个文件中字符的出现次数,每个文件使用一个线程,然后打印总出现次数。

这是我的代码:

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/

相关文章:

c++ - 从多个线程调用 C 文件中的函数

c - 是否有一种机制可以尝试锁定多个互斥量之一?

C - 特定天数是多少小时?

c - 在 C 中实现 yield

c - 无法使用c打开文件

go - 什么是 golang 中的同步(sync.RWMutex)

c++ - 确保函数在lock_guard下运行

c - 如何使用 GObject 按名称调用函数?

c - 客户端/服务器中的 write()/read(),C 中的 pthread 应用程序在非主线程上总是返回 -1?

android - 如何在android上实现实时音频处理?