C ++ Vector,另一个线程的push_back崩溃了吗?

时间:2010-12-10 14:57:50

标签: c++ multithreading stl vector thread-safety

我使用经过检查的STL实现在我的代码中出现意外的断言故障。

经过一些研究后,我将问题缩小到了一个向量中的push_back,该向量来自与创建向量的线程不同的线程。

重现此问题的最简单的代码是:

class SomeClass
    {
    private:
        std::vector<int> theVector;
    public:
        SomeClass () 
        {
            theVector.push_back(1); // Ok
        }


        void add()
     {
          theVector.push_back(1); // Crash 
     }
};

唯一的区别是SomeClass是从我的主线程实现的,而add是从另一个线程调用的。然而,没有一个简洁的问题:在我用于排除故障的最简单的代码形式中,除了我上面提到的情况之外,没有人从这个向量中读取或写入。

跟踪push_back代码,我注意到std :: vector中的一些方法(如count()或size())返回垃圾,当它从另一个thred(方法“add”)调用时,并且从调用时调用正确的值创建线程(例如在构造函数中)

我是否应该断定std :: vector在多线程环境中不可用?或者是否有解决此问题的方法?

编辑:删除易失性

编辑2:你认为这个问题可能不在于多线程吗?在我的测试运行中,add只被调用一次(使用断点验证)。如果我从构造函数中删除push_back,我仍然会崩溃。所以最后,即使只调用一个向量的方法,在一次调用的函数中也会使断言失败。因此,不能有可靠性,或......?

4 个答案:

答案 0 :(得分:8)

std::vector绝对可以在多线程环境中使用,前提是您不能同时从两个线程访问向量。我一直都没有遇到麻烦。

由于vector不是问题,因此您需要更仔细地查看同步机制,因为这很可能是问题所在。

我注意到您将vector标记为volatile。您是否期望将其volatile提供同步?因为它不会。 See here for more information

编辑:最初提供了错误的链接。这已经修复了。抱歉混淆。

答案 1 :(得分:2)

如果你可以保证在调用push_back时没有人写入或读取向量,那么就没有理由它会失败。您可能正在处理更高级别的内存损坏。您应该验证“this”指向SomeClass的真实实例,检查其他成员等。

答案 2 :(得分:1)

标准库是否支持多线程是实现定义的。您必须阅读特定编译器的文档。

另外,你可以做的是添加一些日志消息,如下面的代码所示:

class SomeClass
    {
    private:
        volatile std::vector<int> theVector;
    public:
        SomeClass () 
        {
            std::cout << "SomeClass::SomeClass" << std::endl;
            theVector.push_back(1); // Ok
        }
        ~SomeClass ()
        {
            std::cout << "SomeClass::~SomeClass" << std::endl;
        }
        void add()
        {
            std::cout << "SomeClass::add" << std::endl;
            theVector.push_back(1);
        }
};

确保在调用SomeClass函数时,add的实例仍然存在。

答案 3 :(得分:1)

大多数STL实现都不是线程安全的。您需要使用线程同步(例如互斥)来防止两个线程在访问向量时互相踩踏。基本上,您需要做的是创建一个包含向量的类,以及保护向量以进行读写操作的互斥锁和访问器函数。