stl向量并发读取线程安全吗?

发布于 2024-12-05 03:36:33 字数 335 浏览 2 评论 0原文

我正在开发一个应用程序,其中需要大量线程迭代字符串值集,并尝试将其自己的数据与列表中可用的数据进行匹配。

我正在寻找以下用例:

  1. Vector 使用 std::string 类型的几个元素进行初始化。 (假设对象名称是 strList)。 strList 将在应用程序启动时初始化。
  2. 所有线程都将迭代 strList 以查看其值是否与 strList 的至少一个元素匹配。
  3. 没有线程会尝试修改 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:

  1. 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.
  2. All threads will iterate over strList to see if it's value matches with atleast one element of strList.
  3. 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 技术交流群。

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

发布评论

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

评论(3

路弥 2024-12-12 03:36:33

对于您提到的情况,,它是完全线程安全的。


实际上,STL 并不是正确的引用方式。
它是C++ 标准库

C++03 标准根本没有讨论并发性,因此并发性方面被忽略作为编译器的实现细节。因此,您应该在编译器附带的文档中寻找与并发相关的答案。

大多数 STL 实现本身不是线程安全的。
但对于从多个线程并发读取同一对象而言,大多数 STL 实现确实是线程安全的。

参考文献:

MSDN 说:

单个对象对于从多个线程读取是线程安全的。例如,给定一个对象 A,同时从线程 1 和线程 2 读取 A 是安全的。

Dinkumware STL 文档 说:

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

GCC 文档 说:

我们目前使用 SGI STL对线程安全的定义,其中规定:

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

所以从上面来看,是的,是线程在 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:

A single object is thread safe for reading from multiple threads. For example, given an object A, it is safe to read A from thread 1 and from thread 2 simultaneously.

The Dinkumware STL-Documentation says:

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

GCC Documentation says:

We currently use the SGI STL definition of thread safety, which states:

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.

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.

暮凉 2024-12-12 03:36:33

C++0x FDIS (n3290) 中对此有具体提及。

§ 17.6.5.9 避免数据竞争

整段都很有趣,但更具体地说:

3/ C++ 标准库函数不得直接或间接修改当前线程以外的线程可访问的对象 (1.10),除非通过函数的非常量参数直接或间接访问对象,包括这个。

意味着您可以安全地在 std::vector 上调用 cbegincend 。以及在 std::string 上调用 operator==operator<

6/对通过调用标准库容器或字符串成员函数获得的迭代器进行的操作可以访问底层容器,但不得修改它。

意味着仅仅迭代容器不应该以任何方式修改所述容器。

尽管3/,但全局对象似乎还有空间,因为迭代器修改某种共享寄存器对象,在该对象中它们将自己与容器相关联(STL 调试功能)。我不明白:

7/ 如果对象对用户不可见并且受到数据竞争保护,则实现可以在线程之间共享自己的内部对象。

否则。

无论如何,该标准保证对向量进行迭代是安全的......但在实际读取对象(这些对象是您自己的)时不做任何保证。在本例中,这是因为 std::string 已在上面介绍。

编辑:正如 David Hammen 公正指出的那样,该标准尚未完全实施。许多编译器已经提供了上述保证,尽管以前的标准从未谈到线程。 MSVC、gcc、clang、icc、comeau等...所有大牌都应该已经提供了这个保证,从Als的回答中可以看出。

There is a specific mention in the C++0x FDIS (n3290) for this.

§ 17.6.5.9 Data race avoidance

The whole paragraph is of interest but more particularly:

3/ A C++ standard library function shall not directly or indirectly modify objects (1.10) accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function’s non-const arguments, including this.

means that you may call cbegin and cend on std::vector<T> safely. As well as calling operator== or operator< on std::string.

6/ Operations on iterators obtained by calling a standard library container or string member function may access the underlying container, but shall not modify it.

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:

7/ Implementations may share their own internal objects between threads if the objects are not visible to users and are protected against data races.

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 because std::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.

烟织青萝梦 2024-12-12 03:36:33

除了有关避免数据竞争的通用规则之外,该标准在 [container.requirements.dataraces] 中还指出

-1- 为了避免数据竞争 (17.6.5.9),实现应将以下函数视为 constbeginend、<代码>rbegin、<代码>撕裂、<代码>前、<代码>后、<代码>数据、<代码>查找, lower_boundupper_boundequal_rangeat 以及(关联或无序关联容器中除外)operator[ ]

因此,即使您调用非常量 begin()/end() 等,只要您实际上不修改任何内容,它就是安全的。

In addition to the generic rules about data race avoidance, in [container.requirements.dataraces] the standard says

-1- For purposes of avoiding data races (17.6.5.9), implementations shall consider the following functions to be const: begin, end, rbegin, rend, front, back, data, find, lower_bound, upper_bound, equal_range, at and, except in associative or unordered associative containers, operator[].

So even if you call the non-const begin()/end() etc. as long as you don't actually modify anything it's safe.

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