我有一个STL映射,其中包含对多个线程中操作的对象的共享指针。正在删除shared_ptr所拥有的对象,而智能指针仍然存在于容器和/或其他功能的范围内。所有shared_ptr实例都按值传递(因此滥用引用不会出现问题)。我对来自此源here的印象是,只要存在shared_ptr的实例(从现有的shared_ptr复制),它所拥有的对象就不会被释放。
基本上我正在做的事情:
/* Remove Event response in Thread A */
std::map<std::string, std::shared_ptr<object>>::iterator it = objects.find(id);
if(it != objects.end())
{
std::shared_ptr<object> ob = it->second;
objects.erase(it);
//Do cleanup work with ob
}
/* Add Event response in Thread B */
std::map<std::string, std::shared_ptr<object>>::iterator it = objects.find(id);
if(it == objects.end())
{
std::shared_ptr<object> ob(new object(id));
objects[id] = ob;
//Do setup work with ob
}
/* Duty Cycle Event response in Thread C (very frequent) */
//Take snapshot of objects so Remove Event does not invalidate iterators of duty cycle
std::map<std::string, std::shared_ptr<object>> temp_objects = objects;
for(std::map<std::string, std::shared_ptr<object>>::const_iterator it = temp_objects.begin(); it != temp_objects.end(); ++it)
{
std::shared_ptr<object> ob = it->second;
//Access violation can (but doesn't always) occur when dereferencing ob (ob is empty)
}
我做错了什么?我是否滥用共享指针或对其运作方式做出不正确的假设?
答案 0 :(得分:12)
shared_ptr
个对象的引用计数是原子的;这是C ++ 11所要求的。但是,不需要的是 std::map
操作是原子的。他们当然不是。
无法保证您可以从一个线程插入并从另一个线程中删除,并仍然保持map
内容的完整性。因此,除非您输入自己的互斥锁或其他同步,以防止map
本身的竞争条件,否则您的代码将会中断。
这与shared_ptr
无关;这只是问题的症状。这是关于包含它们的map
。