我需要在多线程环境中保护对STL容器的读取访问吗
Do I need to protect read access to an STL container in a multithreading environment?
我有一个std::list<>容器和这些线程:
-
一个无限添加元素的编写器线程。
-
一个读写器线程,用于在可用时读取和删除元素。
-
几个读取器线程访问容器的SIZE(通过使用SIZE()方法)
有一个普通的互斥锁,它保护前两个线程对列表的访问。我的问题是,大小读取器线程也需要获取这个互斥体吗?我应该使用读/写互斥吗?
我在一个使用Visual C++6的windows环境中。
更新:看起来答案还不清楚。总结一下主要的疑问:考虑到我不需要确切的值(即我可以假设+/-1的变化),即使SIZE读取器线程只调用SIZE()(返回一个简单变量),我仍然需要保护它们吗?竞争条件如何使我的size()调用返回无效值(即与好值完全无关的值)?
答案:通常情况下,必须保护读取器线程以避免出现争用情况。尽管如此,在我看来,更新中提到的一些问题还没有得到回答。
提前感谢!
谢谢大家的回答!
是的,读取线程将需要某种互斥控制,否则写入将改变它下面的内容。
一个读写器互斥应该足够了。但严格来说,这是一个具体实施的问题。实现可能具有可变成员,即使是在代码中只读的const对象中也是如此。
检查由英特尔的开源线程构建块库提供的并发容器。在"代码示例"页面的"容器代码段"下查看一些示例。它们具有用于向量、哈希映射和队列的并发/线程安全容器。
我不相信STL容器是线程安全的,因为没有一种好的方法可以跨平台处理线程。对size()的调用很简单,但它仍然需要保护。
这听起来是一个使用读写锁的好地方。
您应该考虑一些SLT实现可能会在调用时计算大小
为了克服这个问题,你可以定义一个新的变量
volatile unsigned int ContainerSize = 0;
仅在已受保护的更新调用中更新变量,但您可以在没有保护的情况下读取/测试变量(考虑到您不需要确切的值)。
是。我建议用一个强制串行访问的类来包装STL库。或者找到一个已经调试过的类似类。
在这种情况下,我会说不。
如果没有互斥,您可能会发现,在添加或删除项时,size()偶尔会返回错误的值。如果这对你来说是可以接受的,那就去做吧。
然而,如果你需要列表的准确大小,而读者需要知道,那么除了添加和删除调用之外,你还必须在每个大小调用周围放一个关键部分。
PS。VC6 size()只是返回_size内部成员,因此没有互斥对象对您的特定实现来说不会有问题,只是在添加第二个元素时它可能会返回1,反之亦然。
PPS。有人提到了RW锁,这是一件好事,尤其是当您稍后想访问列表对象时。将您的互斥对象更改为Boost::shared_mutex将是有益的。但是,如果您调用的只是size(),则不需要任何互斥。
VC++版本6中的STL不是线程安全的,请参阅最近的问题。看来你的问题有点无关紧要。即使你做得很好,你仍然可能会遇到问题。
- 理解boost::asio-async_read在无需读取内容时的行为
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 使用新行和不使用新行读取文件
- 如何使用 STL C++读取文件和保存连字符
- 如何使用 STL 中的容器读取文件
- STL堆栈:读取访问冲突
- 将文件读取到stl矢量时删除rn
- STL stack top()函数即使在pop()之后也会读取相同的值
- STL正在从文件中读取
- 从文件中读取数据并填写 STL 向量
- 如何在 c++ STL 文件读取期间可移植地捕获和处理 UTF "EN DASH"缺点?
- 使用STL容器从c++中读取.mat文件的Matlab API
- 如何从类似文件的输入中读取可变大小的字符到stl字符串中
- STL文件的哪种格式读取速度更快:ascii还是二进制
- 从文件中读取可变大小的2D-STL矢量
- 读取输入行并将其解析为STL存储c++
- 通过使用指向igzstreams的指针的STL向量来读取gzip文件
- 从二进制文件读取复数值到STL向量
- 是否有必要锁定STL容器以读取其数据?
- 我需要在多线程环境中保护对STL容器的读取访问吗