C ++多线程和向量

时间:2013-12-02 12:12:53

标签: c++ multithreading vector

我尝试了以下算法的各种实现,但总是在程序运行一段时间后崩溃......

我有一个基础对象

class Element
    {
    public:
        int a;
        float p;
        Element(int _a, float _p=1.0): a(_a), p(_p){};
    };

我创建了一个向量并包含在Buffer对象中。

class Buffer
    {
    public:
        Buffer(){};

        vector<Element> raw;       
        vector<Element> optimised; // DATA CALCULATED BASED ON RAW

        void addElement(int _a,float _p=1.0) // FILL THE RAW BUFFER
        {
            raw.push_back(Element(_a,_p));
        }

        void compute()  // COMPUTE THE OPTIMISED BUFFER
        {
            float t;
            int i;
            for(std::vector<Element>::iterator it = raw.begin(); it != raw.end(); ++it) 
            {
                optimised.push_back(Element(it->a,it->p));
                // DO SOME COMPUTATIONALLY INTENSIVE CALCULATIONS
                for(i=1; i<9999999; i++)
                    t = 9./i;
            }
        };

        void clear() // ERASE BOTH BUFFERS
        {
            raw.clear();
            optimised.clear();
        }
    };

我有一个Buffer对象的声明 - 负责捕获当前数据流 - 以及Buffer对象的向量 - 表现得像以前创建的缓冲区的历史/队列。

Buffer buffer;
vector<Buffer> queue;

主线程负责填充缓冲区对象 - 一旦系列完成 - 将缓冲区提交到队列中。 一旦将新缓冲区添加到队列中,就会在单独的线程上调用Compute()函数来分析最近提交的数据。

//ADD THE CURRENT BUFFER TO THE QUEUE
queue.push_back(buffer);

//RUN 'COMPUTE' IN PARALLEL/BACKGROUND ON THE LAST SUBMITTED BUFFER
std::thread t(&Buffer::compute, &queue.back());
t.detach();

//CLEAR THE BUFFER, READY FOR A NEW SERIES
buffer.clear();

该程序符合正常并启动,但在执行期间崩溃(有时在提交一个缓冲区之后,有时在一些缓冲区之后......如果只有一个缓冲区,它通常“工作时间更长”在队列中的某个时间)。

在这种情况下我是否需要使用互斥锁?如果是这样,在哪里?

您对如何优化数据收集有任何建议(填充'缓冲'对象并将其提交到队列中) - 我认为AddElement()有点不必要的昂贵?

感谢任何帮助!

由于

1 个答案:

答案 0 :(得分:2)

问题在于&queue[last]。这会为您提供指向矢量当前存储缓冲区的位置的指针。如果向量重新分配(push_back可以这样做),则指针无效。

有一些解决方案:

  • 将指针存储在queue向量中。像vector<unique_ptr<Buffer>> queue这样的东西会起作用(并确保你不会意外泄漏内存)。
  • 使用不会失效的数据结构在修改时使指针无效。 listdeque将有效。
  • 确保向量不重新分配。您最初可以resize(x),然后自己跟踪最后一个。

更新:添加代码示例。这在Coliru(http://coliru.stacked-crooked.com/

上编译并运行正常
#include <memory>
#include <vector>
#include <iostream>
class Buffer {};

int main()
{
    std::unique_ptr<Buffer> buffer {new Buffer()};
    std::vector<std::unique_ptr<Buffer>> queue;
    for (int i = 0; i < 10; i++) {
        buffer.reset(new Buffer());
        // Do things to buffer;
        queue.push_back(move(buffer));
    }
    std::cout << queue.size() << std::endl;
}