线程内嵌套 std::thread 的错误会引发错误
Error nested std::thread inside a thread throws an error
我试图通过这个简单的测试在另一个线程中创建一个嵌套线程,但它总是失败。尝试删除这个嵌套函数,代码本身运行良好。
代码example/test:
#include <thread>
#include <iostream>
#include <vector>
void simple() { std::cout << "\nNested Thread"; }
void function(int number, int* sum, std::vector<std::thread>& thread_group) {
*sum += number;
// Starting this nested function simple() in a thread causes errors.
// The problem occurs even when there's only a single iteration of the loop.
// Without it the code works fine, even with 10000 iterations.
std::thread ct(simple);
thread_group.push_back(std::move(ct));
}
int main(){
// Container for storing threads
std::vector<std::thread> thread_group;
int sum = 0;
for (int n = 1; n <= 10; n++) {
std::thread t(function, n, &sum, std::ref(r), std::ref(thread_group));
// Add the newly created thread to the container
thread_group.push_back(std::move(t));
}
// Wait for all threads to finish
join_all(thread_group);
return 0;
}
话虽这么说,我需要找到一种方法来调用一个独立的函数,该函数可以 运行 而不会阻止其余代码的执行。线程或其他一些多处理方式在我的程序中非常重要,因为每个函数都是递归的,并不断调用具有不同参数的自身的多个副本,直到满足条件。
我不知道在 std::thread 库中是否可行。尝试使用 Poco 和 boost,但遇到了其他问题,因此决定坚持使用 std::thread。
我在 Windows 10 上使用 Visual Studio 2022。
您正在同时从多个线程读取和写入 sum
和 thread_group
。一个简单的解决方案是确保一次只有一个线程可以访问它们,方法是使用 std::mutex
并在访问这些变量时将其锁定。您还需要确保所有线程在 thread_group
被销毁之前完成工作。我添加了一个计数器和一个 std::condition_variable
来处理这个问题。
示例(使用 C++20 std::jthread
s 而不必调用 non-existing join_all
函数):
#include <condition_variable>
#include <iostream>
#include <list> // using list instead of vector to avoid realloc
#include <mutex>
#include <thread>
#include <vector>
using container = std::list<std::jthread>;
void simple() { std::cout << "Nested Thread\n"; }
void function(int& counter, std::mutex& mtx,
std::condition_variable& cv, container& thread_group)
{
std::lock_guard lock(mtx);
thread_group.emplace_back(simple);
++counter; // so that main thread can check that all is done
cv.notify_one(); // signal main that the work is done
}
int main(){
// Container for storing threads
container thread_group;
std::mutex mtx;
std::condition_variable cv;
int starting_threads = 10;
int counter = 0;
for (int n = 1; n <= starting_threads; n++) {
std::lock_guard lock(mtx); // lock while adding thread
// Add thread to the container
thread_group.emplace_back(function, std::ref(counter), std::ref(mtx),
std::ref(cv), std::ref(thread_group));
}
std::unique_lock lock(mtx);
// wait until all threads are done with thread_group
// before letting thread_group go out of scope and get
// destroyed
while(counter < starting_threads) cv.wait(lock);
std::cout << thread_group.size() << '\n';
// wait for all threads to finish (jthread's auto-join)
}
可能的输出:
Nested Thread
Nested Thread
Nested Thread
Nested Thread
Nested Thread
Nested Thread
Nested Thread
Nested Thread
Nested Thread
20
Nested Thread
我试图通过这个简单的测试在另一个线程中创建一个嵌套线程,但它总是失败。尝试删除这个嵌套函数,代码本身运行良好。
代码example/test:
#include <thread>
#include <iostream>
#include <vector>
void simple() { std::cout << "\nNested Thread"; }
void function(int number, int* sum, std::vector<std::thread>& thread_group) {
*sum += number;
// Starting this nested function simple() in a thread causes errors.
// The problem occurs even when there's only a single iteration of the loop.
// Without it the code works fine, even with 10000 iterations.
std::thread ct(simple);
thread_group.push_back(std::move(ct));
}
int main(){
// Container for storing threads
std::vector<std::thread> thread_group;
int sum = 0;
for (int n = 1; n <= 10; n++) {
std::thread t(function, n, &sum, std::ref(r), std::ref(thread_group));
// Add the newly created thread to the container
thread_group.push_back(std::move(t));
}
// Wait for all threads to finish
join_all(thread_group);
return 0;
}
话虽这么说,我需要找到一种方法来调用一个独立的函数,该函数可以 运行 而不会阻止其余代码的执行。线程或其他一些多处理方式在我的程序中非常重要,因为每个函数都是递归的,并不断调用具有不同参数的自身的多个副本,直到满足条件。
我不知道在 std::thread 库中是否可行。尝试使用 Poco 和 boost,但遇到了其他问题,因此决定坚持使用 std::thread。
我在 Windows 10 上使用 Visual Studio 2022。
您正在同时从多个线程读取和写入 sum
和 thread_group
。一个简单的解决方案是确保一次只有一个线程可以访问它们,方法是使用 std::mutex
并在访问这些变量时将其锁定。您还需要确保所有线程在 thread_group
被销毁之前完成工作。我添加了一个计数器和一个 std::condition_variable
来处理这个问题。
示例(使用 C++20 std::jthread
s 而不必调用 non-existing join_all
函数):
#include <condition_variable>
#include <iostream>
#include <list> // using list instead of vector to avoid realloc
#include <mutex>
#include <thread>
#include <vector>
using container = std::list<std::jthread>;
void simple() { std::cout << "Nested Thread\n"; }
void function(int& counter, std::mutex& mtx,
std::condition_variable& cv, container& thread_group)
{
std::lock_guard lock(mtx);
thread_group.emplace_back(simple);
++counter; // so that main thread can check that all is done
cv.notify_one(); // signal main that the work is done
}
int main(){
// Container for storing threads
container thread_group;
std::mutex mtx;
std::condition_variable cv;
int starting_threads = 10;
int counter = 0;
for (int n = 1; n <= starting_threads; n++) {
std::lock_guard lock(mtx); // lock while adding thread
// Add thread to the container
thread_group.emplace_back(function, std::ref(counter), std::ref(mtx),
std::ref(cv), std::ref(thread_group));
}
std::unique_lock lock(mtx);
// wait until all threads are done with thread_group
// before letting thread_group go out of scope and get
// destroyed
while(counter < starting_threads) cv.wait(lock);
std::cout << thread_group.size() << '\n';
// wait for all threads to finish (jthread's auto-join)
}
可能的输出:
Nested Thread
Nested Thread
Nested Thread
Nested Thread
Nested Thread
Nested Thread
Nested Thread
Nested Thread
Nested Thread
20
Nested Thread