多线程不像预期的那样行动

Multi-threading not acting as expected

本文关键字:多线程      更新时间:2023-10-16

我正在编写一个c 程序,该程序接收文件输入并计算某些字符发生的次数。具体来说,我想使用多线程来解决此问题,以获得多线程的经验。但是,我每次执行都会收到不同的结果,并且想知道我可能会出错的地方 - 仍在学习C 。任何意见将是有益的。

#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <fstream>
#include <bits/stdc++.h> 
#define NUM_THREADS 5
const char flag = 'w';
int totalSum = 0;
bool matchesFlag(char letter) {
    return letter == flag;
}
void *processText(void *threadArg) {
    std::string text = *static_cast<std::string*>(threadArg);
    totalSum += std::count_if(text.begin(), text.end(), matchesFlag);
    pthread_exit(NULL);
}
int main() {
    std::ifstream inFile;
    pthread_t threads[NUM_THREADS];
    inFile.open("text.txt");
    std::string line;
    while (inFile.good()) {
        getline(inFile, line);
        int created = -1;
        while (created) {
            for (int i = 0; i < NUM_THREADS && created != 0; ++i) {
                created = pthread_create(&threads[i], NULL, processText, (void *)&line);    
            }
        }
    }
    std::cout << totalSum << std::endl;
    return 0;
}

所以,让我们看一下到目前为止写的问题和评论。

stackoverflow提出的,我们应该是新成员并遵循行为准则。

然后我们应该尝试提供帮助。

首先评论:

您不使用std ::线程的原因吗? - 2785528

好吧,可能有很多原因。也许BOPAS2使用C 98。也许他是Linux低级爱好者。也许,BOPAS2是C 编程的新手,并且想学习和理解。无论如何,这只是一个示例代码。

我的提议是:如果有C 11(或更高版本(的编译器,则应使用此功能,您应该开始学习新的C 线程功能。

下一个评论

我看到所示代码至少有四个基本问题。按照设计,显示的代码无法正确同步多个线程,更不用说启动四个线程的原因到底是什么,其目的是在每行中计数相同的字母,因此希望获得最终数量的四倍,这是四倍但是由于缺乏同步和原子性,最终结果将是完全随机的,更不用说std :: string将脱离范围并在这些线程完成之前被销毁,导致行为不确定,并随机崩溃。 - Sam Varshavchik

是的,确实存在此代码中的问题。但是,如果您查看代码,则每行只有一个线程。只要失败并且PTHREAD_CREATE返回-1,它将尝试5次。如果PTHREAD_CREATE成功,它将返回0,并且循环将终止。很可能,PTHREAD_CREATE将始终成功,将线程句柄始终覆盖并在线程的数组位置0中。覆盖不好,但在此示例中不会损害。因为pthread_create的结果将在以后不会使用。关于我的理解,无需同步任务(例如与JOIN或其他任何任务(:也不是问题。当它超出范围时,std ::字符串不是问题。STD :: String Line有一个本地副本(螺纹局部变量(。由于上述内容,永远不会随机崩溃。

下一个评论

为什么要为文件的每一行创建5个线程,这些线程都重复每行相同的任务?你到底是什么?

这是一个错误的陈述。每个读行只有一个线程。如果有多行,则启动了多个线程。然而。我不建议使用这种错误处理/恢复策略。

最后评论

建议 - 确保您阅读了有关此主题的大量文献,并在开始之前了解了良好的样本程序。学习如何正确编写MT程序不应通过反复试验来完成。MT编程不仅仅涉及学习如何启动线程

这是真的。多任务是最复杂的,需要大量阅读,实践和长期的理解。大多数认为自己正在理解多线程的人,根本不知道。我都不是。

但是每个人都需要开始。。。

我对问题的分析和回答是(我不确定(:

线程函数的启动以及线程函数参数threadarg的本地副本,可能比读取下一行。这意味着,可以在读取下一行之后复制该变量。而且由于使用指针,因此可能会产生影响。因此,在一个测试中,可以正确解释一条线,并且在下一个运行中可以延迟阅读。这将导致不同的结果。

第二个问题是" Totalsum ="。在这里,我们进行阅读(没问题(和写作。可能有一个所谓的种族状况。2个线程试图访问相同的全局变量。然后在分配过程中进行胎面变化,在该分配中,可以使用两次旧的Vaible。但是在这里,我不确定,比我更专业的人需要判断。

,但一般规则是:如果您像示例中的示例中写入全局变量,请在此操作过程中保护线程更改。有不同的方法。最常见的是使用静音(在这里我不能对所有这些都详细介绍(或关键部分,锁或条件变量或STD :: Atomic或您提供的操作系统提供的任何内容。

重要的是,您甚至可以防止将变量写两次的可能性。在大多数情况下,应避免全局变量。

也许阅读此内容会给您更多的见解。

我希望我至少可以帮助一点。