我有一个std :: map,多个线程用它来存储数据。地图声明如下:
std::map<int, Call> calls;
从每个线程,我必须获取一个互斥锁,获取指向该属性的对象的指针或引用,然后释放互斥锁。之后我可以修改对象,因为每个对象只由一个线程使用。一旦线程死亡,地图中的相应对也将被删除。
我想知道实现这个的最佳方法。我在考虑两种方式:
1)我知道这个人看起来非常疯狂,但仍然是
std::map<int, Call> calls;
...
{
mutex.lock();
Call* callptr = &calls[id];
mutex.unlock();
// use callptr
}
或2)我觉得这个看起来更明智
std::map<int, std::auto_ptr<Call> > calls;
...
{
mutex.lock();
std::auto_ptr<Call> callptr = map[id];
mutex.unlock();
// use callptr
mutex.lock();
map[id] = callptr;
mutex.unlock();
}
线程实际上是在不同的dll中创建的,我没有代码。我正在编写的这个dll由该dll导入并使用。所以它必须只用std :: map实现,但是有人可以告诉我其中一种方法是否正常,或者是否有办法使它更稳定。
由于
答案 0 :(得分:5)
你应该使用迭代器:
mutex.lock();
std::map<int, Call>::iterator callptr = calls.find(id);
callptr->second.foo();
...
mutex.unlock();
带指针的第一个解决方案存在问题,因为地图中对象的生命周期是不确定的 - 当插入或删除元素时重新平衡树时,可能会移动它。
您的第二个解决方案根本不起作用,因为std::auto_ptr
无法满足mapped_type
std::map
的要求 - 主要是因为它的复制构造函数和operator=
不是实际上是复制。您可能不会收到编译器错误,但在运行时会出现非常奇怪的行为。
答案 1 :(得分:3)
根据我Thread Local storage,对你来说是最好的选择。
如果您需要特定于线程的数据,则可以使用线程本地存储,并完全不需要映射和互斥锁定。
答案 2 :(得分:2)
不要在STL容器中使用auto_ptr。别。实现者实际上需要尝试在那里使用编译错误。标准容器往往会复制周围的东西。这对auto_ptr来说是非常错误的。