程序输出有时仅出现在多线程程序中

时间:2011-06-21 10:32:26

标签: c++ multithreading boost-thread cout

我正在使用boost线程来并行化程序中的计算。控制器对象管理计算作业和结果。我创建了一堆工作线程,当主线程显示结果时,它们从控制器对象获取作业。结果需要以正确的顺序显示。为实现这一点,我在std::deque中使用了boost期货。 GetNewJob()在双端队列的末尾添加一个新的boost::promise并返回一个指针。 GetNextResult()从队列的前端获取结果。如果还没有准备好结果,它会阻塞调用线程。

我的Controller类的重要部分:

class Controller
{
public:
    Controller();
    boost::shared_ptr<boost::promise<Results> > GetNewJob();
    Results GetNextResult();

    class NoJobsLeft{};
    class NoResultsLeft{};

private:
    bool JobsLeft() const;
    bool ResultsLeft() const;

    std::deque<boost::shared_ptr<boost::promise<Results> > > queue_;
    boost::mutex mutex_;
    boost::condition_variable condition_;
};

工人职能:

void DoWork()
{
    try
    {
        while(true)
        {
            boost::shared_ptr<boost::promise<Results> >
                    promise(controller.GetNewJob());

            //do calculations

            promise->set_value(results);
        }
    }
    catch(NoJobsLeft)
    {
    }
}

主程序代码:

Controller controller(args);

boost::thread_group worker_threads;

for (unsigned i = 0; i < n_cpus; ++i)
    worker_threads.create_thread(DoWork);

try
{
    while(true)
    {
        Results results = controller.GetNextResult();

        std::cout << results;
        std::cout << std::endl;
    }
}
catch(NoResultsLeft)
{
}

worker_threads.join_all();

有时这很好用,所有结果都会显示出来。 但很多时候我根本看不到任何输出。

我不在工作线程中使用cout


GetNewJob()GetNextResult()的实施:

boost::shared_ptr<boost::promise<Results> > Controller::GetNewJob()
{
    boost::lock_guard<boost::mutex> lock(mutex_);

    if (!JobsLeft())
        throw NoJobsLeft();

    //determine more information about the job, not important here

    queue_.push_back(boost::make_shared<boost::promise<Results> >());

    condition_.notify_one();

    return queue_.back();
}


Results Controller::GetNextResult()
{
    boost::shared_ptr<boost::promise<Results> > results;
    {
        boost::unique_lock<boost::mutex> lock(mutex_);

        if (!ResultsLeft())
            throw NoResultsLeft();

        while(!queue_.size())
        {
            condition_.wait(lock);
        }

        results = queue_.front();
        queue_.pop_front();
    }

    return results->get_future().get();
}

bool Controller::ResultsLeft() const
{
    return (queue_.size() || JobsLeft()) ? true : false;
}

1 个答案:

答案 0 :(得分:2)

如果您没有看到任何输出,则可能会抛出NoResultsLeft,因为第一次传递队列中没有任何内容。另一种可能性是它首先没有向队列添加内容或者抛出NoJobsLeft。在catch块中添加std::cout语句可能有助于识别正在发生的事情。

但是,如果结果无法异步显示,那么您没有理由等待所有这些机制。不能保证线程完成顺序只是通过boost::promise将结果添加到队列的顺序,因此您必须至少在GetNextResult中阻塞,直到第一个线程完成为止。< / p>

如果您想要按顺序显示结果,您的控制器可以采用相同的方式收集所有结果并触发boost::function,以便在一切就绪后以正确的顺序显示结果。

修改

BTW while(!queue_.size())确实应该是while(queue_.empty())而技术上任何非零都被解释为名为size()length()的真实方法,等等当用作如果条件。同样适用于return (queue_.size() || JobsLeft()) ? true : false; return (!queue.empty() || JobsLeft());