【发布时间】:2022-01-24 03:03:09
【问题描述】:
我在 C++ 中创建了一个程序,当使用 for 循环创建线程向量的组件时它不起作用,而当它们被硬编码时它会起作用。 这是硬编码的例子:
std::vector<std::thread> ThreadVector;
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[0], 0);})));
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[1],1);})));
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[2],2);})));
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[3],3);})));
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[4],4);})));
for(auto& t:ThreadVector)
t.join();
maxLast 是一个整数,它是双字符数组的值。 vals 变量是一个三元组字符数组,考虑一个向量中的字符串向量。最后一个值是通过函数发送的数字。 cl.run 函数基本上只需要一个 char 数组,将 maxLast 变量写入文件,然后在下一行写入数组中的下一个字符串。文件名叫trying加号再.txt函数如下图:
void dir::run(int nums, char *vals[nums], int count){
std::cout<<"got started "<<nums<<" "<<count<<std::endl;
std::string filestr = "trying"+std::to_string(count)+".txt";
for(int i = 0; i < nums; i++){
writeLine(std::to_string(nums), filestr);
writeLine(std::string(vals[i]), filestr);
}
}
void dir::writeLine(std::string w, std::string p){
FILE* stream = fopen(p.c_str(), "a+");
fputs(w.c_str(), stream);
fputs("\n", stream);
fclose(stream);
}
当硬编码到如上所示的ThreadVector 变量中运行时,它可以完美运行。但是,如果我按以下方式运行它,将会有一个名为 trying5.txt 的文件,还会有我从未放入打印到文件上的 char 数组中的字符串。也会有一些线程收到相同的i 值。
int i;
int ques=5;
for(i = 0; i < ques; i++){
printf("running %d\n", i);
ThreadVector.emplace_back(std::move(std::thread([&](){cl.run(maxLast, vals[i],i);})));
}
for(auto& t:ThreadVector)
t.join();
在其中一个运行中打印到终端(清理了一下):
running 0
running 1
running 2
running 3
running 4
got started 30 2
got started 30 2
got started 30 4
got started 30 3
got started 30 4
这显然不是应该发生的,正如提到的,有时终端会打印got started 30 5,我最终会得到一个名为trying5.txt的文件。我也试过push_back而不是emplace_back。
【问题讨论】:
-
多线程不仅仅是知道如何创建线程。您发布的程序中根本没有同步,因此无法保证将执行什么顺序。您无法使用单线程方法或思维方式来处理多线程编程。
-
您通过引用捕获
i。i的值是不可预测的,因为线程的开始时间是不确定的。 -
考虑使用 std::async 代替 std::thread。并不是说那会避免你的“问题”。对于线程,您确实需要知道何时需要为线程提供自己的数据副本以进行处理,或者何时需要共享数据访问权限。在编写线程安全代码之前,您可能想了解按值/引用捕获、std::atomic、std::mutex、std::unique_lock、std::condition_variable、std::shared_ptr 等。至少你得到了 lambda 位,这是一个好的开始 :)
标签: c++ arrays multithreading c++17