[英]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.