我有一個包含物件容器的執行緒池,每當它接收到一條新資料時,它都會使用相同的新資料更新所有物件。作業是在執行緒池的構建上預分配的,這個作業存放在下面的資料成員中
std::map<std::thread::id, std::vector<unsigned>> m_work_schedule
因此,如果一個執行緒的元素在map其中包含元素 1,2 和 3 vector<unsigned>,這意味著它負責在每次新資料點到達時更新索引為 1,2 和 3 的物件。
如果我有 10 個物件和 3 個執行緒,作業計劃可能看起來像這樣
140314357151488... 2, 5, 8,
140314365544192... 1, 4, 7,
140314373936896... 0, 3, 6, 9,
在每個作業執行緒中,它都會進行一些計算,然后將其計算添加到共享聚合變數中。不過我很困惑,因為一旦所有執行緒都完成了,只有最后一個執行緒應該對計算進行最后的潤色。出于某種原因,此塊偶爾會執行兩次:
if( std::prev(m_work_schedule.end())->first == std::this_thread::get_id() ){
std::cout << "about to finalize from thread " << std::this_thread::get_id() << ", which supposedly is equal to " << (--m_work_schedule.end())->first << "\n";
m_working_agg = m_final_f(m_working_agg);
m_out.set_value(m_working_agg);
}
輸出如下所示:
139680503645952... 2, 5, 8,
139680512038656... 1, 4, 7,
139680520431360... 0, 3, 6, 9,
about to finalize from thread 139680520431360, which supposedly is equal to 139680520431360
................
about to finalize from thread 139680503645952, which supposedly is equal to 139680503645952
terminate called after throwing an instance of 'std::future_error'
what(): std::future_error: Promise already satisfied
但是,這段代碼怎么會運行兩次呢?我只是從 閱讀m_work_schedule,但偶爾的性質表明這是某種競爭條件。不過,我正在努力想出任何可能的解釋。
- a
std::map::end()在不同的執行緒中回傳不同的東西嗎? - 一個執行緒的閱讀是否
std::map::end()會影響另一個執行緒的閱讀?** - If the last thread finalizes before all threads are finished working, can it randomly enter this block of code again?
- Can thread ids change?
uj5u.com熱心網友回復:
我敢打賭你的問題就在這里
for(unsigned i=0; i< m_num_threads; i) {
m_threads.push_back( std::thread(&split_data_thread_pool::worker_thread, this));
most_recent_id = m_threads.back().get_id();
m_work_schedule.insert(std::pair<std::thread::id, std::vector<unsigned> >(most_recent_id, std::vector<unsigned>{}));
m_has_new_dyn_input.insert(std::pair<std::thread::id, bool>(most_recent_id, false));
}
當您仍在填充 m_work_schedule_map 時,您正在啟動執行緒。據我所知,沒有鎖。所以你有同時的讀者和作家
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/433426.html
