Do std容器总是在多线程环境中抛出异常
Do std containers always throw exceptions in a multi-threaded environment?
Do containers like std::vector&;friends(我实际上使用的是QList)抛出了一个可捕获的异常,或者如果一个线程在另一个线程读取容器时试图写入容器,这是未定义的行为:
std::vector<std::string> stuff;
另一个线程中的非关键任务(例如拼写检查):
try {
for (std::string& s : stuff) {
//do stuff with s
}
} catch (...) { // Handle all exceptions
//bail out of task
}
主线程:
stuff.erase(std::remove(someIterator), stuff.end());
所以你可以看到,在这里会有一个场景,它可能有一个无效的迭代器,并且会在读取线程中抛出一个异常——它会被捕获并退出任务。
但这只是一种情况——我是否可以依赖从这些容器抛出可捕获的异常,这样我就不需要用互斥锁来保护向量或字符串了?或者在某些情况下,它可能会取消引用nullptr(或其他什么)并导致SEH异常,即我无法捕获并继续的异常。我认为答案是它可能依赖于实现,并且很可能会导致未定义的行为,但我想我会问这个问题。
一般来说,您不能指望对无效迭代器的访问会引发任何类型的异常。结果是"未定义的行为":调用可能会抛出,可能会崩溃,可能会持续数年,然后咬你,可能会破坏程序中其他无关的东西。
标准禁止在标准库的对象和函数上做这种事情:
17.6.4.10/1:
如果从不同线程调用标准库函数可能会引入数据竞争,则程序的行为是未定义的。17.6.5.9中规定了可能发生这种情况的条件。
17.6.5.9/6:
通过调用标准库容器或字符串成员函数获得的迭代器上的操作可以访问底层容器,但不能修改它。[注意:特别是,使迭代器无效的容器操作与与该容器相关联的迭代机上的操作相冲突。--尾注]
类似地,大多数Qt函数都不是线程安全的。
如果您需要在线程之间共享数据,请保护自己免受数据竞争的影响。不要指望图书馆会为你做这件事,除非文件上说它会。
使用无效迭代器本身就是未定义的行为。它并没有像你想的那样抛出异常。所以,即使使用互斥,你的想法(除非我误解了它)也不会成功。
访问同一std::对象的数据争用也是未定义行为的来源。
AFAIK标准对std::vector等人的多线程行为只字未提。但实际上,每个人都将以最直接、最高效的方式实现,这意味着没有任何线程安全性。
MSDN记录了它们实现STL的行为。我希望主流实现之间没有差异。仅供参考MSDN文档的长话短说是,如果您在其他线程中有读取器,并且容器正在被修改,那么行为将是未定义的。
- 如何正确取消析构函数中的 Boost deadline_timer(在多线程环境中)?
- 为什么添加延迟会提高此多线程环境中的数据吞吐量?
- Qt::D irectConnection在多线程环境中使用时如何工作?
- 在多线程环境中正确销毁对象
- 多线程环境中C++内存访问
- 为多线程环境包装 c++ new/delete 的安全/好方法
- 在多线程环境中使用 std::call_once() 初始化
- 在多线程环境中交换C 地图对象
- 在多线程环境中使用 libcurl 会导致与 DNS 查找相关的性能非常慢
- 暂停和恢复多线程环境中另一个线程的线程C++技术建议
- 在多线程环境中,什么可能导致"bad file descriptor"?
- 多线程环境中的输出字符串流出现问题
- 信号处理程序在多线程环境中的功能
- 在多线程环境中使用Mysql++的问题
- C++-SQLite3在多线程环境中泄漏句柄
- 如何改进此代码以便在多线程环境下运行
- 在多线程环境中使用atomic保护两个变量
- 多线程环境中的文档锁定
- XSetWMProtocols 和 glXCreateContext 在多线程环境中调用顺序
- 多线程环境 (OpenMP) 中的 OpenCV 会导致分段错误