简体   繁体   English

std::map::end() 是否从不同的线程返回不同的结果?

[英]does std::map::end() return different results from different threads?

I've got this thread pool that holds a container of objects, and whenever it receives a new piece of data, it updates all the objects with the same new piece of data.我有这个线程池,它包含一个对象容器,每当它收到一条新数据时,它就会用相同的新数据更新所有对象。 The work is preallocated on the construction of the thread pool, and this work is stored in the following data member工作是在线程池的构建上预分配的,这个工作存储在下面的数据成员中

std::map<std::thread::id, std::vector<unsigned>> m_work_schedule

So if a thread's element in this map has the elements 1,2 and 3 in its vector<unsigned> , that means it is responsible for updating the objects with indexes 1,2 and 3 every time a new data point arrives.因此,如果此map中的线程元素在其vector<unsigned>中包含元素 1,2 和 3,则意味着它负责在每次新数据点到达时更新索引为 1,2 和 3 的对象。

If I have ten objects and three threads, the work schedule might look something like this如果我有十个对象和三个线程,工作计划可能看起来像这样

140314357151488... 2, 5, 8, 
140314365544192... 1, 4, 7, 
140314373936896... 0, 3, 6, 9, 

In every worker thread , it does some calculation and then adds its calculation to the shared aggregate variable.在每个工作线程中,它都会进行一些计算,然后将其计算添加到共享聚合变量中。 I'm confused though, because once all the threads are finished, only the final thread is supposed to put the finishing touches on the calculation.不过我很困惑,因为一旦所有线程都完成,只有最后一个线程应该对计算进行最后的润色。 For some reason, this block is occasionally executing twice:由于某种原因,这个块偶尔会执行两次:

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

The output looks like this: output 看起来像这样:

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

How can this block of code run twice, though?但是,这段代码怎么能运行两次呢? I am only reading from m_work_schedule , but the occasional nature of this suggests it's some sort of race condition.我只是在阅读m_work_schedule ,但这种情况的偶尔性质表明这是某种竞争条件。 I'm struggling to think of any possible explanation for this, though.不过,我正在努力想出任何可能的解释。

  • Does a std::map::end() return different things in different threads? std::map::end()在不同的线程中返回不同的东西吗?
  • Does one thread's reading with std::map::end() affect another thread's?**一个线程使用std::map::end()的读取是否会影响另一个线程的读取?**
  • If the last thread finalizes before all threads are finished working, can it randomly enter this block of code again?如果最后一个线程在所有线程都工作完之前就finalize了,它能不能再随机进入这个代码块呢?
  • Can thread ids change?线程 ID 可以更改吗?

I bet your problem is here我打赌你的问题就在这里

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

you are starting the threads while you are still populating the m_work_schedule_map.您在填充 m_work_schedule_map 时启动线程。 And as far as I can see there is no lock.据我所知,没有锁。 So you have simultaneous readers and writers所以你有同时的读者和作家

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从不同的线程访问std :: map - Access std::map from different threads 从另一个容器移动contruct`std :: map` - Move contruct `std::map` from a different container 用不同的线程填充 std::vector - Filling std::vector by different threads 使用和加入来自不同线程的std :: thread对象 - Using and joining a std::thread object from different threads std :: future.get()多次调用(来自不同的线程) - std::future.get() Multiple Calls (from Different Threads) 为什么以不同的顺序使用std :: remove_reference和std :: remove_const会产生不同的结果? - Why does using std::remove_reference and std::remove_const in different order produce different results? 为什么 std::locale(“”).name() 在 clang 和 gcc 上给出不同的结果? - Why does std::locale(“”).name() give different results on clang and gcc? 使用std :: vector作为std :: map的键不会在找不到时使用reserve()返回end() - Using std::vector as a key for std::map does not return end() when not found and using reserve() 在没有同步机制的情况下,由不同线程同时读取单个c ++ std :: map对象是否安全? - Is it safe to read a single c++ std::map object by different threads simultaneously without synchronization mechanisms? 按其他键对std :: map排序? - Sorting an std::map by a different key?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM