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

Program output appears only sometimes in multi-threaded program

本文关键字:程序 多线程 输出      更新时间:2023-10-16

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

我的控制器类的重要部分:

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_;
};

Worker功能:

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

在没有看到任何输出的情况下,它可能会抛出NoResultsLeft,因为第一次通过时队列中没有任何内容。另一种可能性是,它最初未能将内容添加到队列中,或者抛出NoJobsLeft。将std::cout语句添加到捕获块中可能有助于识别正在发生的事情

但是,如果结果不能异步显示,那么就没有理由使用该机制——您不妨全部等待。线程的完成顺序无法保证,只能保证通过boost::promise将结果添加到队列的顺序,因此您必须在GetNextResult中进行阻塞,至少直到第一个线程完成为止。

如果你想按顺序显示结果,你的控制器可以以相同的方式收集所有结果,并在一切就绪时激发boost::function以按正确的顺序显示结果。

编辑:

BTW while(!queue_.size())实际上应该是while(queue_.empty()),而从技术上讲,任何非零的东西都被解释为真正的方法,命名为size()length()等,当用作if条件时,看起来真的很难看。return (queue_.size() || JobsLeft()) ? true : false;也是如此,它可能是return (!queue.empty() || JobsLeft());