简体   繁体   中英

Launching runnable objects in threads out of a C++ std::vector

I have a C++11 program which configures a number of runnable objects, puts them in a std::vector , then launches them all in separate threads. Unfortunately when I iterate over the objects in the vector, I am getting threads launched only for the last object. I've distilled the problem to its core in the following test code (compiled with clang++ -std=c++11 cpp_threadlaunch.cpp using clang 6.0 on OSX 10.9.5).

#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);
}

When I run with goal = "succeed" , I get the hoped-for output

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

When I run with goal = "fail" , I get two copies of the output from only one object, instead of output from each object:

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

I suspect I'm missing something rudimentary here -- would much appreciate it if someone can explain what's going on and what the solution is. Thanks --

The lambda function you're passing to std::thread in the loop captures a by reference. Since a then goes out of scope you have undefined behavior. Capture it by value (using [=] instead of [&] ).

The problem is that you capture the value of 'a' by reference in [&]() { a->run() } You see the last value, because the loop has finished, by the time the other threads run. If you capture by value, using [=] you should get the desired effect.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM