Страницы

Поиск по вопросам

вторник, 16 июля 2019 г.

Не работает программа c std::thread

Не могу понять почему программа с std::thread, то зависает при запуске, а то работает нормально, компилятор MinGW-w64. Видимо ловлю в какойто момент взаимную блокировку, но вот понять в какой не могу. Вот код:
#include #include #include #include #include
using namespace std; mutex m0,m1,m2,m3,m4; condition_variable c1,c2; vector vInt; bool b1 = false; bool b2 = false; int b0=2; bool ext = false;
void add_vect(int i) { lock_guard lg(m0); vInt.push_back(i); };
void gen() { unique_lock lk1(m3); for (int i=1; i<6; ++i) { if (i>1) { // в перовой итерации цикла пропускаем ожидание окончания работы потоков ex1, ex2 c2.wait(lk1,[]{return b0 == 2;}); //ожидание окончания работы потоков ex1, ex2 }; add_vect(1); //тут должна быть функция выполняемая в этом потоке m4.lock(); b0 = 0; b1=true; b2=true; if ( i == 5 ) ext = true; // проверяем последнюю итерацию цикла c1.notify_all(); //разблокируем потоки ex1, ex2 m4.unlock(); }; };
void ex1() { unique_lock lk1(m1); while (!ext) { c1.wait(lk1, []{ return b1; }); //ожидание окончания работы потока gen for (int i = 1; i<10; ++i) { add_vect(2); //тут должна быть функция выполняемая в этом потоке }; m4.lock(); b1=false; b0++; if (b0 == 2) //проверяем что этот поток последний завершает работу c2.notify_one(); //разблокируем поток gen m4.unlock(); }; };
void ex2() { unique_lock lk1(m2); while (!ext) { c1.wait(lk1, []{ return b2; }); for (int i = 1; i<10; ++i) { add_vect(3); //тут должна быть функция выполняемая в этом потоке }; m4.lock(); b2=false; b0++; if (b0 == 2) //проверяем что этот поток последний завершает работу c2.notify_one(); //разблокируем поток gen m4.unlock(); }; };
int main() { thread tgen(gen); thread t1(ex1); thread t2(ex2); tgen.join(); t1.join(); t2.join();
for (vector ::iterator it=vInt.begin(); it != vInt.end(); ++it){ cout << *it; };
return 0; }
По времени потоки должны работать так:


Ответ

Вот вам скелет, должно в принципе работать. Обошёлся одним общим мьютексом.
#include #include #include #include #include
using namespace std;
mutex global;
condition_variable allow_ex_cond; int allow_iteration = -1;
condition_variable finished_ex_cond; int finished_ex = 0;
bool shutdown = false;
const int num_workers = 2;
void gen() { cout << "coordinator working, iteration -1" << endl;
const int maxiterations = 3; for (int i = 0; i < maxiterations; i++) { { unique_lock l(global);
// start new iteration finished_ex = 0; allow_iteration = i; shutdown = (i == maxiterations - 1);
allow_ex_cond.notify_all();
// wait for threads to finish task finished_ex_cond.wait(l, [] { return finished_ex == num_workers; }); }
// do work cout << "coordinator working, iteration " << i << endl; } }
void excommon(int num) { int iteration = 0; while (true) { // do work cout << "worker " << num << ", iteration " << iteration << endl;
{ unique_lock l(global);
// signal finished finished_ex++; if (finished_ex == num_workers) finished_ex_cond.notify_all();
// check exit if (shutdown) break;
iteration++;
// wait for signal to continue allow_ex_cond.wait(l, [iteration] { return allow_iteration == iteration; }); } } cout << "worker " << num << " shutting down" << endl; }
void ex1() { excommon(1); }
void ex2() { excommon(2); }
int main(int argc, char* argv[]) { thread tgen;
{ unique_lock l(global); tgen = thread(gen); allow_ex_cond.wait(l, [] { return allow_iteration == 0; }); }
thread t1(ex1); thread t2(ex2);
tgen.join(); t1.join(); t2.join();
return 0; }

Комментариев нет:

Отправить комментарий