Как грамотно завершить неизвестное заранее количество потоков C++?
Здраствуйте, у меня появился вопрос: как грамотно завершить неизвестное заранее количество потоков? Тоесть программа должна запустить одну функцию в несколько потоков, вот пример:
#include <iostream>
#include <thread>
using namespace std;
int func() { //функция которою выполняют потоки
for(int i=0; i<5; i++)
std::cout << "hello" << endl;
return 0;
}
int main() {
int numb;
cin>>numb; //пользователь вносит количество потоков
for ( int j = 0; j <= numb; j++ ) {
new std::thread(func);
}
//здесь main должна ждать
cout<<"bonjour"<<endl;
return 0;
}
Но проблема в том, что функция main не дожидается завершения потоков и влезает посередние. Вот что я имею ввиду:
root@PCKali:/home/kali/eclipse-workspace/test/Debug# ./test
5
hello
hello
hellohello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello**bonjour**
hello
hello
hello
hello
hello
hello
hello
hello
hello
bonjour появляется между hello (Выделил звёздочками), а мне нужно чтобы main дожидалась окончании потоков. Я знаю про функцию .join(); но я не знаю что писать перед точкой, так как названия потокам не даётся, потому что пользователь выбирает их количество. Может я делаю не правильно ещё на этапе создания потоков? Подскажите, пожалуйста. (Надеюсь всё нормально объяснил, если вдруг что - спрашивайте в комментах)
Ответы (2 шт):
#include <mutex>
#include <vector>
#include <thread>
#include <iostream>
int main()
{
int numb;
std::cin >> numb;
std::mutex threadMtx;
std::vector<std::thread> threads;
threads.reserve(numb);
for (int id = 0; id < numb; ++id) {
threads.emplace_back(std::thread([&threadMtx](){
for (uint8_t cn = 1; cn <= 5; ++cn) {
std::lock_guard<std::mutex> lockGuard(threadMtx);
std::cout << "From Thread " << std::this_thread::get_id()
<< " >> Hello [ " << std::to_string(cn) << " ] " << std::endl << std::flush;
}
}));
}
for (auto &thread : threads) {
if (thread.joinable()) {
thread.join();
}
}
std::cout << "Bonjour" << std::endl;
return EXIT_SUCCESS;
}
Сonsole output:
3
From Thread 139909013223168 >> Hello [ 1 ]
From Thread 139909013223168 >> Hello [ 2 ]
From Thread 139909013223168 >> Hello [ 3 ]
From Thread 139909013223168 >> Hello [ 4 ]
From Thread 139909013223168 >> Hello [ 5 ]
From Thread 139908996437760 >> Hello [ 1 ]
From Thread 139908996437760 >> Hello [ 2 ]
From Thread 139908996437760 >> Hello [ 3 ]
From Thread 139908996437760 >> Hello [ 4 ]
From Thread 139908996437760 >> Hello [ 5 ]
From Thread 139909004830464 >> Hello [ 1 ]
From Thread 139909004830464 >> Hello [ 2 ]
From Thread 139909004830464 >> Hello [ 3 ]
From Thread 139909004830464 >> Hello [ 4 ]
From Thread 139909004830464 >> Hello [ 5 ]
Bonjour
(1) создаем num потоков с функцией foo в контейнере vector
(2) присоединяем потоки к главному потоку обычным проходом по vector с применением метода join
#include <iostream>
#include <thread>
#include <vector>
void foo() {} // функция которую выполняют потоки
int main()
{
int num;
std::cin >> num; // пользователь вносит количество потоков
std::vector<std::thread> threads;
threads.reserve(num);
for (int i = 0; i < num; ++i) { // (1)
threads.emplace_back(foo);
}
for (auto& thread : threads) { // (2)
thread.join();
}
std::cout << "only master thread is working here\n";
return 0;
}
что касается вашего участка кода:
- создавая объект потока с помощью
newвы ни где не сохраняете указатель на выделенную память, если уж вам нужны указатели на потоки, то закидывайте указатели вvectorнапример, потомjoinилиdetachих, и уж потом позаботьтесь об освобождении памяти выделенной под каждыйthread - синхронизация потока вывода в теле вашей функции
funcтема отдельного вопроса и об этом стоит позаботиться