Я пытаюсь создать доказательство концепции межпотоковой связи с помощью значений общего состояния: основной поток создает рабочие потоки, давая каждому отдельный вектор по ссылке, позволяет каждому выполнять свою работу и заполнять свой вектор результатами, инаконец, собирает результаты.
Однако происходят странные вещи, для которых я не могу найти объяснения, кроме какой-то расы между инициализацией векторов и запуском рабочих потоков.Вот код.
#include <iostream>
#include <vector>
#include <thread>
class Case {
public:
int val;
Case(int i):val(i) {}
};
void
run_thread (std::vector<Case*> &case_list, int idx)
{
std::cout << "size in thread " << idx <<": " << case_list.size() << '\n';
for (int i=0; i<10; i++) {
case_list.push_back(new Case(i));
}
}
int
main(int argc, char **argv)
{
int nthrd = 3;
std::vector<std::thread> threads;
std::vector<std::vector<Case*>> case_lists;
for (int i=0; i<nthrd; i++) {
case_lists.push_back(std::vector<Case*>());
std::cout << "size of " << i << " in main:" << case_lists[i].size() << '\n';
threads.push_back( std::thread( run_thread, std::ref(case_lists[i]), i) );
}
std::cout << "All threads lauched.\n";
for (int i=0; i<nthrd; i++) {
threads[i].join();
for (const auto cp:case_lists[i]) {
std::cout << cp->val << '\n';
}
}
return 0;
}
Протестировано на repl.it (gcc 4.6.3), программа выдает следующий результат:
size of 0 in main:0
size of 1 in main:0
size of 2 in main:0
All threads lauched.
size in thread 0: 18446744073705569740
size in thread 2: 0
size in thread 1: 0
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
exit status -1
На моемкомпьютер, кроме чего-то подобного выше, я также получаю:
Segmentation fault (core dumped)
Похоже, что поток 0 получает вектор, который не был инициализирован, хотя вектор кажется должным образом инициализированным в main.
Чтобы изолировать проблему, я попытался перейти на однопоточность, изменив строку:
threads.push_back( std::thread( run_thread, std::ref(case_lists[i]), i) );
на
run_thread(case_lists[i], i);
и закомментировав:
threads[i].join();
Теперь программа работает, как и ожидалось, с «потоками», запускающимися один за другим до того, как основное собирает результаты.
Мой вопрос: что не так с многопоточной версиейвыше?