2015-12-10 1 views
4

У меня есть программа C++ 11, которая настраивает несколько запущенных объектов, помещает их в std::vector, а затем запускает их все в отдельных потоках. К сожалению, когда я перебираю объекты в векторе, я запускаю потоки только для последнего объекта. Я переделал проблему в ее ядро ​​в следующем тестовом коде (скомпилирован с clang++ -std=c++11 cpp_threadlaunch.cpp с использованием clang 6.0 на OSX 10.9.5).Запуск запущенных объектов в потоках из C++ std :: vector

#include <iostream> 
#include <thread> 
#include <vector> 
#include <unistd.h> 

std::mutex outputlock; 

class agent { 

public: 
    agent(std::string name) : m_name(name) {}; 
    ~agent(void) {}; 

    void run(void) { 
     while (1) { 
      outputlock.lock(); 
      std::cout << "Agent: " << m_name << std::endl; 
      outputlock.unlock(); 
      sleep(1); 
     } 
    } 
    std::string  getName(void) { return m_name; } 

private: 

    std::string  m_name; 
}; 

int main() 
{ 
    std::vector<std::thread>  threads; 
    std::vector<agent*>    agents; 
    // std::string     goal = "succeed"; 
    std::string      goal = "fail"; 

    agents.push_back(new agent("A")); 
    agents.push_back(new agent("B")); 

    if (goal == "succeed") { 

     threads.push_back(std::thread([&]() { agents.at(0)->run(); })); 
     threads.push_back(std::thread([&]() { agents.at(1)->run(); })); 

    } 
    else { 

     for (auto it = agents.begin(); it != agents.end(); it++) { 

      agent* a = *it; 

      std::cout << "Launching thread for " << a->getName() << std::endl; 

      threads.push_back(std::thread([&]() { a->run(); })); 
     } 
    } 

    for (auto it = threads.begin(); it != threads.end(); it++) { 

     it->join(); 
    } 

    exit(0); 
} 

Когда я бегу с goal = "succeed", я получаю желанный для выходных

Agent: A 
Agent: B 
Agent: A 
Agent: B 

Когда я бегу с goal = "fail", я получаю две копии на выходе только от одного объекта, а не выход из каждого объект:

Launching thread for A 
Launching thread for B 
Agent: B 
Agent: B 
Agent: B 
Agent: B 

Я подозреваю, что я что-то элементарное не хватает здесь - было бы очень признателен, если кто-то может объяснить, что происходит и что решение я s. Спасибо -

+1

Отклоните свой код ... меньше. – LogicStuff

+0

Я бы порекомендовал 'emplace_back' вместо' push_back (new ...) '. – erip

+0

Также вы можете использовать 'std :: for_each' для соединения потоков. :) – erip

ответ

12

Функция лямбда вы переходите к std::thread в петле захватывает a по ссылке. Начиная с a, тогда выходит за пределы области действия, у которой есть неопределенное поведение. Захватите его по значению (используя [=] вместо [&]).

1

Проблема заключается в том, что вы захватить значение «а» по ссылке в [&]() { a->run() } Вы видите последнее значение, так как цикл закончен, к тому времени другие потоки выполняются. Если вы фиксируете значение, используя [=], вы должны получить желаемый эффект.

+0

Добавили ли вы что-то, чего не было в другом ответе, или вы просто опубликовали то же самое, но без форматирования? – LogicStuff

+0

Здесь не было другого ответа, когда я разместил свой. – Anton

+0

Он говорит, что другой ответ на 10 минут старше, и вы могли бы обновить страницу во время ввода. Я не отправляю сообщение, если кто-то бьет меня до секунд. – LogicStuff

Смежные вопросы