stl映射查找线程安全

发布于 2024-11-05 05:17:51 字数 31 浏览 0 评论 0原文

stl map 上的 find 调用线程安全吗?

Is find call on stl map thread safe?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

硬不硬你别怂 2024-11-12 05:17:51

不,C++ 规范不保证规范中对任何 STL 容器上的操作的线程安全性。如果线程安全很重要,那么您应该提供自己的锁定。

话虽这么说,不同的实现似乎提供了不同的保证。例如,大多数似乎允许多个并发读取器,只要没有同时执行写入即可。如果您不关心可移植性,您可以研究您的实现文档。例如,来自此处的 SGI STL:

STL 的 SGI 实现是
线程安全仅在以下意义上
同时访问不同的
容器是安全的,并且同时
对共享容器的读访问
是安全的。如果多个线程访问一个
单个容器,并且至少一个
线程可能会写,然后
用户有责任确保
线程之间的互斥
在容器访问期间。

这个答案来看,类似的保证似乎是由 Dinkumware 制作(他们制作了 Microsoft 的 STL 实现)。

多线程可以安全地读取
相同的容器对象。 (有
内不受保护的可变子对象
一个容器对象。)

两个线程可以安全地操作
的不同容器对象
相同类型。 (没有不受保护的
内部共享静态对象
容器类型。)

您必须防止同时发生
访问容器对象如果在
至少有一个线程正在修改
目的。 (明显的同步
原语,例如
Dinkum 线程库,不会
被容器对象颠覆。)

No, the C++ spec makes no guarantees on thread safety in the spec for operations on any STL containers. If thread safety is important, the you should provide your own locking.

That being said, different implementations seem to offer different guarantees. Most seem to allow multiple concurrent readers, for example, as long as no writing is being performed concurrently. If you don't care about portability, you can research the documentation for your implementation. For example from here for SGI STL:

The SGI implementation of STL is
thread-safe only in the sense that
simultaneous accesses to distinct
containers are safe, and simultaneous
read accesses to to shared containers
are safe. If multiple threads access a
single container, and at least one
thread may potentially write, then the
user is responsible for ensuring
mutual exclusion between the threads
during the container accesses.

From this answer, a similar guarantee seems to be made by Dinkumware (they make Microsoft's STL implementation).

Multiple threads can safely read the
same container object. (There are
nunprotected mutable subobjects within
a container object.)

Two threads can safely manipulate
different container objects of the
same type. (There are no unprotected
shared static objects within a
container type.)

You must protect against simultaneous
access to a container object if at
least one thread is modifying the
object. (The obvious synchronization
primitives, such as those in the
Dinkum Threads Library, will not be
subverted by the container object.)

愿得七秒忆 2024-11-12 05:17:51

否:当另一个线程与您的查找同时更新地图时,行为是未定义的。

No: when another thread is updating the map concurrently with your find, behavior is undefined.

我早已燃尽 2024-11-12 05:17:51

我试图找到问题的答案。

https://gcc.gnu.org/onlinedocs /libstdc++/libstdc++-html-USERS-3.4/stl__map_8h-source.html

可以看到stl地图源。


搜索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     }

I tried to find the answer to the question.

https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-3.4/stl__map_8h-source.html

you can see stl map souce.


search find(). It is found in 497 line, 524 line. Code is written as _M_t.find(__x);


Then search _M_t.

It is found in 124 line.
It is written as _Rep_type _M_t;


If property _M_t is created per thread, It could be thread safe.
But I don't think so.
If 2 thread use find concurrently, they would use _M_t concurrently.
_Rep_type is connected to _Rb_tree.

You can see _Rb_tree in below source.

https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.1/stl__tree_8h-source.html

find() do tree travel(see below code).
unwilled change in __x and __y would occur.

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     }
白云悠悠 2024-11-12 05:17:51

实际上,Microsoft Visual Studio 2008 附带的 STL 似乎对修改映射的操作有一些锁定(我假设它对于 set 是相同的)。这是相当烦人的,因为我正在多个线程中构建更多地图,这会影响我的性能。

Actually, the STL shipped with Microsoft Visual Studio 2008 seems to have some locks on operations that modify the map (and i assume it is the same for set). It is rather annoying, as i'm building more maps in multiple threads and it is killing my performance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文