我希望在能够同时添加和擦除元素的同时转储unordered_map的键。它需要4秒才能完全倾倒,太长了。是否可以在单独的线程中进行转储,如下所示:
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
}在主线程中,我有:
pthread_mutex_lock( &mutex );
map.erase(iter);无序映射的erase方法有问题吗,因为擦除后迭代器将无效。
有没有其他安全的并行转储方法?
发布于 2013-02-03 22:37:17
对于unordered_map (以及一般的关联容器),erase()成员函数不会使迭代器和对除已删除元素以外的其他元素的引用无效。
然而,在这里,您可能会擦除一个元素并使其迭代器失效,而您的循环持有该元素的迭代器:例如,如果您碰巧擦除了要在您的循环中取消引用的下一个迭代器所引用的元素。
因此,您需要注意您要删除的元素不会被您要在while周期的下一个循环中处理的迭代器引用:
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是循环中使用的迭代器变量。
发布于 2013-02-03 22:39:59
请参阅:What happens if you call erase() on a map element while iterating from begin to end?
由于您在调用调用erase的do_this方法之前增加了迭代器,因此不会造成任何问题。
仅供参考:使用您当前的算法,我认为您根本不需要互斥锁。
发布于 2013-02-03 22:46:08
您可以通过迭代存储桶而不是迭代元素来获得部分(但不是全部--这实际上只是允许您交错操作,以便擦除不必等待完整的4秒)。只要不减少存储桶计数,这将是安全的
即
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 _的线程在看到这个值时执行实际的擦除。
https://stackoverflow.com/questions/14673549
复制相似问题