C++ std::vector自然线程安全迭代
假设我有std::vector和两个线程 第一个线程正在处理擦除函数,而第二个线程在for循环中 这种情况是线程安全的吗 第二个线程会继续运行还是引发异常C++ std::vector自然线程安全迭代,c++,c++11,C++,C++11,假设我有std::vector和两个线程 第一个线程正在处理擦除函数,而第二个线程在for循环中 这种情况是线程安全的吗 第二个线程会继续运行还是引发异常 #include <iostream> #include <vector> #include <thread> int main() { std::vector<int> intContainer; for ( int index = 0; index <= 10000
#include <iostream>
#include <vector>
#include <thread>
int main()
{
std::vector<int> intContainer;
for ( int index = 0; index <= 100000; ++index){
intContainer.push_back(index);
}
std::thread t1([&](){
while ( 1 ){
intContainer.erase( std::find(intContainer.begin(), intContainer.end(), random(1, 100000) ) );
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
});
std::thread t2([&] (){
for ( auto& val : intContainer ){
std::cout << val << std::endl;
}
});
t1.join();
t2.join();
return 0;
}
这是线程不安全的,但也是未定义的行为 这是线程不安全的,因为您在遍历向量时正在更改元素和向量本身 这是一种未定义的行为,因为存在上述点竞争,但也因为您正在擦除向量中任何位置的元素,这意味着您正在有效地使用于在另一个线程中迭代的所有迭代器失效。因此,即使这是一个单线程程序,例如使用光纤,您仍然可以使用UB 请注意,不会抛出异常,因为某些内容不是线程安全的。当然,这并不意味着错误——腐败、崩溃等——不会发生——它们肯定会发生
此外,请注意,两个线程都不会停止运行。他们会继续下去,而不知道自己把一切都搞砸了。关键是他们没有办法知道。这不是线程安全的。这是UB。查看或线程。如果我不关心向量中的对象是否被删除,它会继续循环或抛出错误吗?特别是考虑读和。它不仅是线程安全的,它也是同一线程中的UB,从向量中删除数据,使所有迭代器无效!编辑的回答:只是一个侧面,MSVC在使用调试符号编译时可能会抛出异常,消息说向量迭代器不兼容:-由于数据的原因,这也是未定义的行为race@Zereges当然,如果您使用某种工具进行调试,您可能会幸运地发现它。这是w.r.t.写的。语言提供的保证,不管怎样,即使一个工具可以给你这样的保证,代码也不会这样写:@Caleth的确,谢谢-编辑了一点以反映这一点,并且还解释了UB即使在单线程的情况下也会发生。