上下文
我有一个类(让我们说Foo
)管理一些集中式资源作为静态地图中的历史记录,有一个读取它们的访问器和一个添加新数据的函数(没有办法删除一个键):
class Foo
{
private:
static std::map<std::string,MyDataStructure> data;
public:
static const MyDataStructure& getData(const std::string& key)
{
assert(Foo::data.count(key) > 0); // Must exist
return Foo::data[key];
}
static void addData(const std::string& key, const MyDataStructure& d)
{
assert(Foo::data.count(key) == 0); // Can not already exist
Foo::data[key] = d;
}
};
为了避免并发问题,我添加了一个我这样管理的互斥锁:
class Foo
{
private:
static std::map<std::string,MyDataStructure> data;
static boost::mutex mutex_data;
public:
static const MyDataStructure& getData(const std::string& key)
{
boost::mutex::scoped_lock lock(Foo::mutex_data);
assert(Foo::data.count(key) > 0); // Must exist
return Foo::data[key];
}
static void addData(const std::string& key, const MyDataStructure& d)
{
boost::mutex::scoped_lock lock(Foo::mutex_data);
assert(Foo::data.count(key) == 0); // Can not already exist
Foo::data[key] = d;
}
};
我的问题
Foo::data
返回的getData
的引用:此引用是在互斥锁范围之外使用的,那么它是否可能出现问题?由于另一个访问添加数据,是否可能丢失引用?简而言之:地图中的引用始终是一样的吗?assert
需要addData
吗?如果我更改链接到地图中现有密钥的数据,参考会更改吗?getData
是否需要锁定?我想也许不是std::map
已经是多线程安全的。答案 0 :(得分:2)
请参阅Lifetime of references in STD collections
“对于
std::map
,只要您不清除地图,或者删除特定的引用元素,引用就是有效的;插入或删除其他元素就没问题。”
根据上面的规则,不...修改地图中已有的引用只是调整同一地址的位。 (只要您不通过删除密钥实施修改,然后再次重新添加该密钥。)
请参阅C++11 STL containers and thread safety
因此锁定是必需的,因为在addData()
插入期间,地图结构的“内部布线”可能会处于不稳定状态......在{{1}的查找遍历期间,布线可能会被触发没有警卫。
但是,如果您手头有参考,则可以在添加或删除期间阅读或编写已存在的getData()
引用之一。这只是从地图到参考导航的过程,需要确保在导航过程中没有人在写。