Как одновременно запустить несколько потоков, созданных циклом, с помощью boost.thread?

Я изучаю основы boost.thread. Пока что я могу создавать каждый поток один за другим вручную, чтобы они могли работать одновременно. Однако при создании цикла он выполняется последовательно, а не параллельно.

#include <iostream>
#include <boost/thread.hpp>
void workerFunc()
{
  boost::posix_time::seconds workTime(3);
  std::cout << "Worker: Running" << '\n';
  boost::this_thread::sleep(workTime);
  std::cout<< "Worker: Finished" << '\n';
}

int main()
{
  std::cout << "main: startup" << '\n';
  boost::thread workerThread(workerFunc);
  std::cout << "main: waiting for thread" << '\n';
  //these are ok
  boost::thread t(workerFunc), t2(workerFunc), t3(workerFunc), t4(workerFunc);     
  t.join();
  t2.join();
  t3.join();
  t4.join();
  //these are not
  for (int i = 0; i < 2; ++i)
    {
      boost::thread z(workerFunc);
      z.join();
    }
  std::cout << "main:done" << '\n';
  return 0;
}

person Amumu    schedule 02.06.2011    source источник


Ответы (3)


  for (int i = 0; i < 2; ++i)
    {
      boost::thread z(workerFunc);
      z.join();
    }

Вы начинаете свой поток и сразу же ждете его завершения!

ИЗМЕНИТЬ

Один из нескольких альтернативных хаков помимо групп потоков.

  std::vector<boost::thread *> z;

  for (int i = 0; i < 2; ++i)
    z.push_back(new boost::thread(workerFunc));

  for (int i = 0; i < 2; ++i)
  {
      z[i]->join();
      delete z[i];
  }
person Duck    schedule 02.06.2011
comment
Итак, я думаю, мне следует поместить все потоки в цикле в контейнер и запустить его позже с другим циклом? Что ж, я попытался сделать это так, как обычно делаю в Java. - person Amumu; 02.06.2011
comment
Это должно действовать так же и в Java. Вы не создаете поток № 2 до того, как уже присоединились к потоку № 1 (или потоку № 0 для пуристов). Для некоторой помощи в отладке вы можете получить идентификатор потока, вызвав boost::this_thread::get_id() - person Jan; 02.06.2011
comment
Как мне тогда положить его в контейнер? Это не позволяет мне помещать объекты boost::thread в контейнер. - person Amumu; 02.06.2011
comment
Амуму нельзя копировать тред объекты. Поддерживает ли ваш компилятор семантику перемещения или режим C++0x? - person Duck; 02.06.2011
comment
не могли бы вы объяснить в noobspeak, почему второй работает? заранее большое спасибо! - person ; 12.09.2013
comment
@Gracchus Путешествие по переулку памяти. Два отдельных вопроса. (1) OP запускал поток и немедленно присоединялся к нему (блокировался до его завершения) в цикле, поэтому одновременно мог работать только один поток. (2) ОП хотел поместить объекты своего потока в вектор. Векторы делают копии вставленных в них данных, и вы не можете копировать объекты-потоки. Таким образом, второй обходит это, динамически создавая потоки и помещая (скопированные) указатели на потоки в векторе. Сами объекты потока не копируются. - person Duck; 12.09.2013
comment
Спасибо! почему цикл for блокируется, когда точно такой же синтаксис прямо перед этим не блокируется? еще раз заранее спасибо! - person ; 12.09.2013
comment
@Gracchus Блокируют не циклы for, а вызовы внутри них. Конструктор потока не блокируется. Соединение делает. - person Duck; 12.09.2013
comment
еще раз большое спасибо! так что постер неверен, что t...t4 не работают параллельно? я очень ценю это! - person ; 12.09.2013
comment
Потоки t1..t4 работают параллельно. Его цикл for не работает. - person Duck; 12.09.2013
comment
не могли бы вы объяснить, почему это здесь? stackoverflow.com/questions/18769221/ теперь я перестану загрязнять ваш ответ;)) я очень ценю вашу помощь! - person ; 12.09.2013
comment
@Gracchus Мне действительно нечего добавить. Приведенный ответ абсолютно правильный. - person Duck; 12.09.2013
comment
мы получаем ошибку: нет соответствующего конструктора для инициализации 'boost::thread' - person bicepjai; 25.09.2015

Хорошо, я нашел ответ через проблему кого-то другого, а также узнал их проблему:

Как выполнить boost::thread_group фиксированное количество параллельных потоков

person Amumu    schedule 02.06.2011
comment
Это обходной путь, но ваш компилятор должен (в конечном итоге) поддерживать то, что вы изначально планировали. - person Duck; 02.06.2011

Использовать shared_ptr

#include <iostream>
#include <boost/thread.hpp>

void workerFunc()
{
    boost::posix_time::seconds workTime(3);
    std::cout << "Worker: Running" << '\n';
    boost::this_thread::sleep(workTime);
    std::cout << "Worker: Finished" << '\n';
}

int main()
{
    std::cout << "main: startup" << '\n';
    std::vector<std::shared_ptr<boost::thread>> z;

    for (int i = 0; i < 2; ++i) {
        z.push_back(std::make_shared<boost::thread>(workerFunc));
    }

    for (auto t : z) {
        t->join();
    }

    std::cout << "main:done" << '\n';
    return 0;
}

Выполнить это

# g++ e.cpp -lboost_thread && ./a.out
main: startup
Worker: Running
Worker: Running
Worker: Finished
Worker: Finished
main:done
person L. Ouyang    schedule 08.11.2018