stl vector并发读取线程安全吗?

Ame*_*Jah 23 c++ concurrency stl thread-safety language-lawyer

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

我正在寻找以下用例:

  1. Vector初始化为几个std :: string类型的元素.(可以说对象名是strList).strList将在应用程序启动时初始化.
  2. 所有线程都将遍历strList以查看它的值是否与strList的至少一个元素匹配.
  3. 没有线程会尝试修改strList,它将严格用作只读对象.

那么请告诉我并发读取是否对矢量对象是线程安全的.我使用的是RHEL 6,gcc版本是4.5.x

Alo*_*ave 39

YES对于你提到的情况下,这是完全线程安全的.


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

C++ 03标准根本不讨论并发性,因此并发性方面被省略为编译器的实现细节.因此,编译器附带的文档是应该查找与并发相关的答案的地方.

大多数STL实现都没有线程安全的,因为这样的.
但是对于来自多个线程的同一对象的并发读取,大多数STL实现确实是线程安全的.

参考文献:

MSDN说:

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

Dinkumware STL-Documentation说:

多个线程可以安全地读取相同的容器对象.(容器对象中有nunprotected mutable子对象.)

GCC文档说:

我们目前使用SGI STL定义的线程安全性,该定义指出:

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

所以从上面可以看出,GCC中的线程安全是从多个线程并发读取同一个对象.

注意:GCC的标准库是SGI的STL代码的衍生物.


Mat*_* M. 9

为此,在C++ 0x FDIS(n3290)中有一个特别的提及.

§17.6.5.9避免数据竞争

整段是有意义的,但更具体的是:

3 / C++标准库函数不应直接或间接修改除当前线程以外的线程可访问的对象(1.10),除非通过函数的非const参数直接或间接访问对象,包括此参数.

意味着你可以调用cbegincendstd::vector<T>安全的.除了打电话operator==operator<std::string.

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

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

虽然3 /尽管如此,但似乎有全局对象的空间,因为迭代器修改某种共享的寄存器对象,在这些对象中它们将自己与容器相关联(STL调试功能).我没理解:

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

除此以外.

无论如何,标准保证迭代vector将是安全的......但是在实际读取对象时(这些是你自己的)不能保证.在这种情况下,这包括在内,因为std::string如上所述.

编辑:正如David Hammen所说,该标准尚未完全实施.许多编译器已经提供了上述保证,即使之前的标准从未提及线程.MSVC,gcc,clang,icc,comeau等......从Als的回答中可以看出,所有大牌都应该已经提供了这种保证.