std :: vector自然线程在迭代时安全

时间:2019-03-19 08:54:01

标签: c++ c++11

假设我有std :: vector和两个线程。

第一个线程正在处理擦除函数,而第二个线程处于 for循环

这种情况是线程安全的吗?

第二个线程会继续运行还是抛出异常?

#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;
}

1 个答案:

答案 0 :(得分:6)

这是线程不安全的,但也是未定义的行为。

它是线程不安全的,因为在迭代时要更改元素(以及向量本身)。

由于上述几点(种族),它是未定义的行为,而且还因为您基本上擦除了向量中任何位置的元素,这意味着您实际上使所有对其的迭代器无效(您正在其他线程中进行迭代) )。因此,即使这是一个单线程程序(例如使用光纤),您仍然会拥有UB。


请注意,由于某些内容不是线程安全的,因此不会引发异常。当然,这并不意味着不会发生错误(例如损坏,崩溃等),并且可以肯定地发生。

此外,请注意,线程(它们都不是)都将“停止运行”。他们将继续前进,而不知道自己搞砸了一切。关键是他们没有办法知道。