是stl向量并发读取线程
我正在研究一个应用程序,在这个应用程序中,需要大量线程遍历字符串值集合,并尝试将它自己的数据与列表中可用的数据进行匹配。
我正在寻找以下用例:
那么你能否告诉我,如果并发读取在向量对象上是线程安全的。 我使用的是RHEL 6,而gcc版本是4.5.x
是的,你提到的场景是完全线程安全的。
实际上,STL并不是正确的引用方式。
它是C ++标准库 。
C ++ 03标准根本不谈论并发性,所以并发性方面被遗漏为编译器的实现细节。 所以编译器附带的文档是应该查看与并发有关的答案的地方。
大多数STL实现不是线程安全的,因为这样的。
但是为了从多个线程同时读取同一对象,STL的大多数实现确实是线程安全的。
参考文献:
MSDN说:
单个对象对于从多个线程读取是线程安全的。 例如,给定一个对象A,同时从线程1和线程2读取A是安全的。
Dinkumware STL文档说:
多个线程可以安全地读取同一个容器对象。 (一个容器对象中有nunprotected可变子对象。)
GCC文档说:
我们目前使用SGI STL定义的线程安全性,其中规定:
STL的SGI实现仅在同时访问不同容器是安全的同时对同一个共享容器的读取访问是安全的意义上是线程安全的。 如果多个线程访问单个容器,并且至少有一个线程可能会写入,则用户负责确保容器访问期间线程之间的相互排斥。
因此,从上面的说明来看,是的,GCC中的线程安全是从多个线程同时读取相同的对象。
注意:GCC的标准库是SGI STL代码的衍生产品。
在C ++ 0x FDIS(n3290)中特别提到了这一点。
§17.6.5.9避免数据竞赛
整个段落是有趣的,但更具体的是:
3 / C ++标准库函数不得直接或间接修改除当前线程以外的线程可访问的对象(1.10),除非通过函数的非const参数直接或间接访问对象,包括这些。
意味着你可以调用cbegin
和cend
上std::vector<T>
安全。 以及在std::string
上调用operator==
或operator<
6通过调用标准库容器或字符串成员函数获得的迭代器操作可以访问基础容器,但不得修改它。
意味着仅仅遍历容器不应以任何方式修改所述容器。
尽管如此,尽管如此,似乎还是有全局对象存在的余地,因为迭代器修改某种共享注册对象,并将它们与容器关联起来(STL调试功能)。 我没有理解:
如果对象对用户不可见并且受到数据竞争保护,实现可以在线程之间共享它们自己的内部对象。
除此以外。
无论如何,标准保证迭代vector
将是安全的......但在实际读取对象(这些是你自己的)时不能保证。 在这种情况下,这是因为std::string
被覆盖在上面。
编辑:正如David Hammen刚刚指出的那样,这个标准还没有完全实施。 许多编译器已经提供了上述的保证,即使之前的标准没有提到线程。 MSVC,gcc,clang,icc,comeau等...所有大牌都应该已经提供了这种保证,从Als的回答中可以看出。
该标准说,除了关于避免数据竞争的通用规则之外,在[container.requirements.dataraces]中
-1-为避免数据竞争(17.6.5.9),实现应将以下函数视为const
: begin
, end
, rbegin
, rend
, front
, back
, data
, find
, lower_bound
, upper_bound
, equal_range
, at
和,除了关联或无序的关联容器, operator[]
。
所以即使你调用非const的begin()
/ end()
等等,只要你没有实际修改任何东西就是安全的。