【发布时间】:2015-12-15 13:14:45
【问题描述】:
STL 不保证其集合的线程安全。但我想知道以下代码是否真的有效。
一个线程通过调用 [] 运算符在映射 m 上调用非常量操作,但使用映射上已经存在的键。据我所知,这只是调用 find() 并返回对 gcc 中迭代器的引用。另一个线程同时持有 m 的 const 迭代器。
问题是:断言会失败吗?
void doBracket(std::map<int, int>& m) {
const auto& val = m[0];
std::cerr << val << std::endl;
}
void doIter(const std::map<int, int>& m){
auto zeroIter = m.find(0);
auto oneIter = m.find(1);
auto twoIter = m.find(2);
assert(zeroIter->second == 0);
assert(oneIter->second == 1);
assert(twoIter->second == 2);
}
int main() {
std::map<int, int> m = {{0, 0}, {1, 1}, {2, 2}};
std::thread mutateThread {doBracket, std::ref(m)};
std::thread constThread {doIter, std:ref(m)};
mutateThread.join();
constThread.join();
}
这是 stl_map 的作用:
operator[](const key_type& __k)
{
// concept requirements
__glibcxx_function_requires(_DefaultConstructibleConcept<mapped_type>)
iterator __i = lower_bound(__k);
// __i->first is greater than or equivalent to __k.
if (__i == end() || key_comp()(__k, (*__i).first))
//handle this case
return (*__i).second;
}
【问题讨论】:
-
无论如何,您的代码都不是线程安全的。每个 ìtererator 更改操作都必须由互斥锁保护。
-
Dieter:我知道标准是这么说的。我对实际的实现更感兴趣。我更新了 stl_map 代码,这似乎暗示该代码实际上是线程安全的。
标签: c++ stl thread-safety