为什么我在C++线程函数调用中得到重复值?
Why am I getting duplicate values in a C++ thread function call?
我很好奇我在这里做错了什么。我有以下功能:
索引器.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::mutex
和std::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*
,并查看您遇到的相同问题。
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 如何将元素添加到数组的线程安全函数?
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 异常属于C++中的线程还是进程
- C++中的线程安全删除
- C++使用params创建线程函数会导致转换错误
- 类与私有变量的其他类之间的线程安全性
- CoInitialize()在单独的线程上崩溃而不返回
- c++中的线程池
- 线程之间的布尔停止信号
- 为什么std::async使用同一个线程运行函数
- 用于矢量处理的多个线程
- C++为线程工作动态地分割例程
- 为什么我不能在 while 循环中创建线程?