为什么我在C++线程函数调用中得到重复值?

Why am I getting duplicate values in a C++ thread function call?

本文关键字:C++ 线程 函数调用 为什么      更新时间:2023-10-16

我很好奇我在这里做错了什么。我有以下功能:

索引器.h:

class DtIndexer {
public:
static void ThreadedIndex(string folderPath);

索引器.cpp

void DtIndexer::ThreadedIndex(string folderPath) {
cout << "t-> Indexing Folder: " << folderPath << endl;
cout << "t->> Done..." << endl;
}

以及我创建线程的呼吁:

void DtIndexer::UpdateIndex(DatabaseData &data, bool isCreate) {
vector<thread> threadList;
for (string &s: data.FilePaths) {
const char *folder = GetFolderPath(s, data.IncludeSubFolders);
cout << "t-> Adding Folder to Thread: " << folder << endl;
threadList.emplace_back(thread(ThreadedIndex, folder));
}
for_each(threadList.begin(), threadList.end(), mem_fn(&thread::join));
}

我的输出是这样的:

-> 将文件夹添加到线程:/index_2185<+>

-> 将文件夹添加到线程:/index_1065<+>

-> 索引文件夹:/index_1065<+>

->> 完成...

-> 索引文件夹:/index_1065<+>

->> 完成...

现在,我很确定它必须处理该方法的静态,但是如果我删除静态,我会得到这个:

错误:无效使用非静态成员函数 'void DtIndexer::ThreadedIndex(std::__cxx11::string)' threadList.emplace_back(thread(ThreadedIndex, folder));

另外,如果我删除static并将函数添加到线程中,如下所示:

threadList.emplace_back(thread(&DtIndexer::ThreadedIndex, folder));

我得到:

从这里需要/usr/include/c++/6/functional:1286:7:错误:静态 断言失败:指向成员的指针参数数错误 static_assert(_Varargs::值

我对C++还很陌生,所以,任何建议都将不胜感激。

替换

const char *folder = GetFolderPath(s, data.IncludeSubFolders);

std::string folder( GetFolderPath(s, data.IncludeSubFolders) );

线程首先按值复制参数,然后复制一个可能指向GetFolderPath函数中的静态缓冲区的const char*。每次调用时,都会覆盖该缓冲区,因此从中读取的线程可能会也可能不会得到您期望的内容。

请注意,您不需要执行emplace_back(std::thread(...,因为您作为参数编写的内容emplace_back将转发到您的vector持有的类型的构造函数,在本例中为std::thread。除非您确实愿意,否则也不需要使线程函数static。您可以从 lambda 开始,捕获this并通过副本folder。您可能会注意到的另一件事是,当许多线程同时写入std::cout时,输出会变得乱码。您可以使用std::mutexstd::lock_guard保护公共资源(如std::cout)免受多个线程的同时访问。

下面是具有非静态线程方法和std::cout保护的类版本:

#include <iostream>
#include <vector>
#include <cstring>
#include <mutex>
#include <thread>
const char* GetFolderPath() {
static std::vector<std::string> paths = {"this is a path", "here is another one",
"what do we have here", "mother of dirs",
"what did the tomatoe ..."};
static size_t idx = 0;
static char buf[256];
std::strcpy(buf, paths[idx].c_str());
idx = (idx + 1) % paths.size();
return buf;
}
class DtIndexer {
std::mutex mtx_cout; // std::cout mutex
public:
void ThreadedIndex(std::string folderPath) {
std::lock_guard lock(mtx_cout); // wait until this thread acquires the mutex
std::cout << "t-> Indexing Folder: " << folderPath << "n";
}
void UpdateIndex() {
std::vector<std::thread> threadList;
{ // lock_guard scope
std::lock_guard lock(mtx_cout); // acquire mutex
for(int i = 0; i < 50; ++i) {
// const char* folder = GetFolderPath();
std::string folder(GetFolderPath());
std::cout << "t-> Adding Folder to Thread: " << folder << "n";
//             safe copy here --+       +--- thread runs here ---+
//                              |       |                        |
//                              V       V                        V
threadList.emplace_back( [this, folder] { ThreadedIndex(folder); });
//                      Δ
//                      |
//                      +-- no std::thread(... needed here
}
} // lock_guard releases mutex here
for(auto& t : threadList) t.join();
}
};
int main() {
DtIndexer a;
a.UpdateIndex();
}

您可以将上面的folder字符串替换为const char*,并查看您遇到的相同问题。