首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在添加和删除元素的同时转储无序映射?

如何在添加和删除元素的同时转储无序映射?
EN

Stack Overflow用户
提问于 2013-02-03 22:31:03
回答 3查看 323关注 0票数 2

我希望在能够同时添加和擦除元素的同时转储unordered_map的键。它需要4秒才能完全倾倒,太长了。是否可以在单独的线程中进行转储,如下所示:

代码语言:javascript
复制
while (1) {
    pthread_mutex_lock( &mutex ); 
    if(iter!=map.end()){
        x=iter->first
        iter++;    
    }
    pthread_mutex_unlock( &mutex );

    do_this(x);  // this takes time to complete
}

在主线程中,我有:

代码语言:javascript
复制
pthread_mutex_lock( &mutex ); 
map.erase(iter);

无序映射的erase方法有问题吗,因为擦除后迭代器将无效。

有没有其他安全的并行转储方法?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-02-03 22:37:17

对于unordered_map (以及一般的关联容器),erase()成员函数不会使迭代器和对除已删除元素以外的其他元素的引用无效。

然而,在这里,您可能会擦除一个元素并使其迭代器失效,而您的循环持有该元素的迭代器:例如,如果您碰巧擦除了要在您的循环中取消引用的下一个迭代器所引用的元素。

因此,您需要注意您要删除的元素不会被您要在while周期的下一个循环中处理的迭代器引用:

代码语言:javascript
复制
pthread_mutex_lock( &mutex ); 
if (i != iter)
{
    map.erase(i);
}
else
{
    // Maybe store in a queue of elements to be removed after the loop is done
}

其中iter是循环中使用的迭代器变量。

票数 3
EN

Stack Overflow用户

发布于 2013-02-03 22:39:59

请参阅:What happens if you call erase() on a map element while iterating from begin to end?

由于您在调用调用erasedo_this方法之前增加了迭代器,因此不会造成任何问题。

仅供参考:使用您当前的算法,我认为您根本不需要互斥锁。

票数 1
EN

Stack Overflow用户

发布于 2013-02-03 22:46:08

您可以通过迭代存储桶而不是迭代元素来获得部分(但不是全部--这实际上只是允许您交错操作,以便擦除不必等待完整的4秒)。只要不减少存储桶计数,这将是安全的

代码语言:javascript
复制
pthread_mutex_lock( &mutex ); 
size_t count = map.bucket_count();
pthread_mutex_unlock( &mutex );

for(size_t i = 0; i<count; ++i){
  pthread_mutex_lock( &mutex );
  for(auto it = map.begin(i); it != map.end(i); ++i)
    do_this(it->first);
  pthread_mutex_unlock( &mutex );
}

如果您想将do_this从互斥中拉出,则需要在其他结构中累加值

根据这个映射在其他地方是如何使用的,另一个建议是,您可以将元素交换为某个已知的无效值,而不是擦除,然后让正在执行转储/ do _的线程在看到这个值时执行实际的擦除。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14673549

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档