簡體   English   中英

程序輸出有時僅出現在多線程程序中

[英]Program output appears only sometimes in multi-threaded program

我正在使用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;
}

如果您沒有看到任何輸出,則可能會拋出NoResultsLeft因為第一次傳遞隊列中沒有任何內容。 另一種可能性是它首先沒有向隊列添加內容或者拋出NoJobsLeft std::cout語句添加到catch塊中可能有助於識別正在發生的事情。

但是,如果結果無法異步顯示,那么您沒有理由等待所有這些機制。 不能保證線程完成順序只是通過boost::promise將結果添加到隊列的順序,所以你必須至少在GetNextResult中阻塞,直到第一個線程完成。

如果要按順序顯示結果,控制器可以以相同的方式收集所有結果並觸發boost::function ,以便在所有內容准備就緒時以正確的順序顯示結果。

編輯:

BTW while(!queue_.size())真的應該是while(queue_.empty())而技術上任何非零被解釋為名為size()真實方法, length()等在用作時非常丑陋如果條件。 return (queue_.size() || JobsLeft()) ? true : false; return (queue_.size() || JobsLeft()) ? true : false; 哪個可以return (!queue.empty() || JobsLeft());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM