stl向量并发读取线程安全吗?
我正在开发一个应用程序,其中需要大量线程迭代字符串值集,并尝试将其自己的数据与列表中可用的数据进行匹配。
我正在寻找以下用例:
- Vector 使用 std::string 类型的几个元素进行初始化。 (假设对象名称是 strList)。 strList 将在应用程序启动时初始化。
- 所有线程都将迭代 strList 以查看其值是否与 strList 的至少一个元素匹配。
- 没有线程会尝试修改 strList 并且它将被严格用作只读对象。
那么您能否告诉我并发读取在向量对象上是否是线程安全的。我使用的是 RHEL 6,gcc 版本是 4.5.x
I am working on a application where huge number of threads are expected to iterate over set of string values and try to match it's own data with the data available in the list.
I am looking for following use case:
- Vector is initialized with few elements of type std::string. (Lets say object name is strList). strList will get initialized at the time of application startup.
- All threads will iterate over strList to see if it's value matches with atleast one element of strList.
- No thread will ever try to modify strList and it will be strictly used as readonly object.
So could you please tell me if concurrent reads are thread-safe on vector object. I am using RHEL 6 and gcc version is 4.5.x
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
对于您提到的情况,是,它是完全线程安全的。
实际上,STL 并不是正确的引用方式。
它是C++ 标准库。
C++03 标准根本没有讨论并发性,因此并发性方面被忽略作为编译器的实现细节。因此,您应该在编译器附带的文档中寻找与并发相关的答案。
大多数 STL 实现本身不是线程安全的。
但对于从多个线程并发读取同一对象而言,大多数 STL 实现确实是线程安全的。
参考文献:
MSDN 说:
Dinkumware STL 文档 说:
GCC 文档 说:
我们目前使用 SGI STL对线程安全的定义,其中规定:
所以从上面来看,是的,是线程在 GCC 中,从多个线程并发读取同一对象是安全的。
注意:GCC 的标准库是 SGI 的 STL 代码的衍生版本。
YES for the scenario you mention, it is perfectly Thread Safe.
Actually, STL is not a correct way of referring it.
It is the C++ Standard Library.
The C++03 Standard does not talk about concurrency at all, So the concurrency aspect is left out as an implementation detail for compilers. So the documentation that comes with your compiler is where one should look to for answers related to concurrency.
Most of the STL implementations are not thread safe as such.
But for concurrent reads of same object from multiple threads most implementations of STL are indeed thread safe.
References:
MSDN says:
The Dinkumware STL-Documentation says:
GCC Documentation says:
We currently use the SGI STL definition of thread safety, which states:
So from the above, Yes it is thread safe in GCC to have concurrent reads of same object from multiple threads.
Note: GCC's Standard Library is a derivative of SGI's STL code.
C++0x FDIS (n3290) 中对此有具体提及。
整段都很有趣,但更具体地说:
意味着您可以安全地在
std::vector
上调用cbegin
和cend
。以及在std::string
上调用operator==
或operator<
。意味着仅仅迭代容器不应该以任何方式修改所述容器。
尽管3/,但全局对象似乎还有空间,因为迭代器修改某种共享寄存器对象,在该对象中它们将自己与容器相关联(STL 调试功能)。我不明白:
否则。
无论如何,该标准保证对向量进行迭代是安全的......但在实际读取对象(这些对象是您自己的)时不做任何保证。在本例中,这是因为
std::string
已在上面介绍。编辑:正如 David Hammen 公正指出的那样,该标准尚未完全实施。许多编译器已经提供了上述保证,尽管以前的标准从未谈到线程。 MSVC、gcc、clang、icc、comeau等...所有大牌都应该已经提供了这个保证,从Als的回答中可以看出。
There is a specific mention in the C++0x FDIS (n3290) for this.
The whole paragraph is of interest but more particularly:
means that you may call
cbegin
andcend
onstd::vector<T>
safely. As well as callingoperator==
oroperator<
onstd::string
.means that merely iterating over a container should not modify the said container in any way.
Despite 3/ though, there seems to be room for global objects though, as iterators modifying some kind of shared register object in which they would associate themselves with the container (STL debug features). I don't make sense of:
otherwise.
Anyway, the Standard guarantees that iterating over the
vector
will be safe... but makes no guarantees when it comes to actually reading the objects (those are your own). In this case, this is covered becausestd::string
is covered above.EDIT: As David Hammen justly noted, this Standard is not yet fully implemented. Many compilers already provided the guarantees above, even though the previous Standard never spoke about threads. MSVC, gcc, clang, icc, comeau, etc... All big names should already provide this guarantee, as can be seen from Als' answer.
除了有关避免数据竞争的通用规则之外,该标准在 [container.requirements.dataraces] 中还指出
因此,即使您调用非常量
begin()
/end()
等,只要您实际上不修改任何内容,它就是安全的。In addition to the generic rules about data race avoidance, in [container.requirements.dataraces] the standard says
So even if you call the non-const
begin()
/end()
etc. as long as you don't actually modify anything it's safe.