提升线程串行运行,而不是并行运行

时间:2011-03-03 10:30:16

标签: c++ multithreading parallel-processing boost-thread

我是C ++中多线程的完全新手,并决定从Boost Libraries开始。另外,我在Vista上使用英特尔的C ++编译器(来自Parallel Studio 2011)和VS2010。

我正在对遗传算法进行编码,并希望利用多线程的好处:我想为群体中的每个个体(对象)创建一个线程,以便他们计算它们的适应性(繁重的操作)并行地减少总执行时间。

据我了解,每当我启动一个子线程时,它就会“在后台”工作,并且父线程继续执行下一条指令,对吗?所以,我想创建并启动我需要的所有子线程(在for循环中),然后等待它们完成(在另一个join()循环中调用每个线程的for)在继续之前。

我面临的问题是第一个循环不会继续下一次迭代,直到新创建的线程完成工作。然后,第二个循环就像去了一样好,因为所有的线程都已经被循环命中时加入。

以下是(我认为是)相关的代码片段。告诉我你还有什么需要知道的。

class Poblacion {
    // Constructors, destructor and other members
    // ...
    list<Individuo> _individuos;
    void generaInicial() { // This method sets up the initial population.
        int i;
        // First loop
        for(i = 0; i < _tamano_total; i++) {
            Individuo nuevo(true);
            nuevo.Start(); // Create and launch new thread
            _individuos.push_back(nuevo);
        }

        // Second loop
        list<Individuo>::iterator it;
        for(it = _individuos.begin(); it != _individuos.end(); it++) {
            it->Join();
        }

        _individuos.sort();
    }
};

并且,线程对象个性化

class Individuo {
    private:
        // Other private members
        // ...
        boost::thread _hilo;

    public:
        // Other public members
        // ...
        void Start() {
            _hilo = boost::thread(&Individuo::Run, this);
        }
        void Run() {
            // These methods operate with/on each instance's own attributes,
            // so they *can't* be static
            generaHoc();
            calculaAptitud();
            borraArchivos();
        }
        void Join() {
            if(_hilo.joinable()) _hilo.join();
        }
};

谢谢! :D

1 个答案:

答案 0 :(得分:7)

如果这是你的真实代码,那么你就有问题了。

    for(i = 0; i < _tamano_total; i++) {
        Individuo nuevo(true);
        nuevo.Start(); // Create and launch new thread
        _individuos.push_back(nuevo);
    }

    void Start() {
        _hilo = boost::thread(&Individuo::Run, this);
    }

此代码在堆栈上创建一个新的Individuo对象,然后启动一个运行的线程,将该堆栈对象的this指针传递给新线程。然后将复制该对象放入list立即销毁堆栈对象,在新线程中留下悬空指针。这会给你未定义的行为。

由于list一旦插入后就永远不会移动内存中的对象,你可以在插入列表后启动线程:

    for(i = 0; i < _tamano_total; i++) {
        _individuos.push_back(Individuo(true)); // add new entry to list
        _individuos.back().Start(); // start a thread for that entry
    }