在stl map线程上找到调用是否安全?
在stl map线程上找到调用是否安全?
不,C ++规范不保证任何STL容器上的操作规范中的线程安全性。如果线程安全很重要,您应该提供自己的锁定。
话虽这么说,不同的实现似乎提供了不同的保证。例如,大多数似乎允许多个并发读取器,只要不同时执行写入。如果您不关心可移植性,可以研究实现的文档。例如来自 这里 对于SGI STL:
STL的SGI实现是 线程安全只在某种意义上说 同时访问不同的 容器是安全的,同时的 读取对共享容器的访问 很安全。如果多个线程访问a 单个容器,至少一个 线程可能会写,然后 用户负责确保 线程之间相互排斥 在容器访问期间。
从 这个答案,Dinkumware似乎也做出了类似的保证(他们制作了微软的STL实现)。
多个线程可以安全地读取 相同的容器对象。 (有 内部的无保护可变子对象 一个容器对象。)
两个线程可以安全地操作 不同的容器对象 相同的类型。 (没有不受保护的 共享静态对象 容器类型。)
你必须防止同时发生 访问容器对象,如果在 至少有一个线程正在修改 目的。 (明显的同步 原语,例如那些 Dinkum Threads Library,不会 被容器对象破坏。)
我试图找到问题的答案。
https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-3.4/stl__map_8h-source.html
你可以看到stl map souce。
搜索 find()
。它位于497行,524行。代码写成 _M_t.find(__x);
然后搜索 _M_t
。
它在124行中找到。
它写成 _Rep_type _M_t;
如果财产 _M_t
是每个线程创建的,它可以是线程安全的。
但我不这么认为。
如果2线程使用 find
同时,他们会使用 _M_t
同时。
_Rep_type
连接到 _Rb_tree
。
你可以看到 _Rb_tree
在下面的来源。
https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.1/stl__tree_8h-source.html
find()
做树旅行(见下面的代码)。
不愿意改变 __x
和 __y
会发生。
01307 template<typename _Key, typename _Val, typename _KeyOfValue,
01308 typename _Compare, typename _Alloc>
01309 typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
01310 _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
01311 find(const _Key& __k)
01312 {
01313 _Link_type __x = _M_begin(); // Current node.
01314 _Link_type __y = _M_end(); // Last node which is not less than __k.
01315
01316 while (__x != 0)
01317 if (!_M_impl._M_key_compare(_S_key(__x), __k))
01318 __y = __x, __x = _S_left(__x);
01319 else
01320 __x = _S_right(__x);
01321
01322 iterator __j = iterator(__y);
01323 return (__j == end()
01324 || _M_impl._M_key_compare(__k,
01325 _S_key(__j._M_node))) ? end() : __j;
01326 }
否:当另一个线程与您的同时更新地图时 find
,行为未定义。
实际上,Microsoft Visual Studio 2008附带的STL似乎对修改映射的操作有一些锁定(我认为它与set相同)。这是相当烦人的,因为我正在多个线程中构建更多的地图,这正在扼杀我的表现。