std::map::end() return 不同线程的结果不同吗?
does std::map::end() return different results from different threads?
我有这个 thread pool,它包含一个对象容器,每当它收到一条新数据时,它就会用相同的新数据更新所有对象。工作是在线程池的构建上预分配的,这个工作存储在下面的数据成员中
std::map<std::thread::id, std::vector<unsigned>> m_work_schedule
因此,如果此 map
中的线程元素在其 vector<unsigned>
中具有元素 1,2 和 3,则意味着它负责更新索引为 1,2 和 3 的对象新数据点到达的时间。
如果我有十个对象和三个线程,工作计划可能看起来像这样
140314357151488... 2, 5, 8,
140314365544192... 1, 4, 7,
140314373936896... 0, 3, 6, 9,
在每个 worker thread 中,它都会进行一些计算,然后将其计算添加到共享聚合变量中。不过我很困惑,因为 一旦所有线程都完成,只有最后一个线程应该对计算进行最后的润色。 出于某种原因,这个块是 偶尔执行两次:
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
读到的,但偶尔的性质表明它是一些某种竞争条件。不过,我正在努力想出任何可能的解释。
std::map::end()
return 在不同的线程中有不同的东西吗?
- 一个线程的阅读
std::map::end()
会影响另一个线程的阅读吗?**
- 如果最后一个线程在所有线程工作完成之前就结束了,它是否可以再次随机进入此代码块?
- 线程 ID 可以更改吗?
我打赌你的问题就在这里
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 时启动线程。据我所知,没有锁。所以你有同时的读者和作家
我有这个 thread pool,它包含一个对象容器,每当它收到一条新数据时,它就会用相同的新数据更新所有对象。工作是在线程池的构建上预分配的,这个工作存储在下面的数据成员中
std::map<std::thread::id, std::vector<unsigned>> m_work_schedule
因此,如果此 map
中的线程元素在其 vector<unsigned>
中具有元素 1,2 和 3,则意味着它负责更新索引为 1,2 和 3 的对象新数据点到达的时间。
如果我有十个对象和三个线程,工作计划可能看起来像这样
140314357151488... 2, 5, 8,
140314365544192... 1, 4, 7,
140314373936896... 0, 3, 6, 9,
在每个 worker thread 中,它都会进行一些计算,然后将其计算添加到共享聚合变量中。不过我很困惑,因为 一旦所有线程都完成,只有最后一个线程应该对计算进行最后的润色。 出于某种原因,这个块是 偶尔执行两次:
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
读到的,但偶尔的性质表明它是一些某种竞争条件。不过,我正在努力想出任何可能的解释。
std::map::end()
return 在不同的线程中有不同的东西吗?- 一个线程的阅读
std::map::end()
会影响另一个线程的阅读吗?** - 如果最后一个线程在所有线程工作完成之前就结束了,它是否可以再次随机进入此代码块?
- 线程 ID 可以更改吗?
我打赌你的问题就在这里
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 时启动线程。据我所知,没有锁。所以你有同时的读者和作家