std :: vector - 线程安全和调整大小选项

时间:2013-12-06 00:28:01

标签: c++ vector thread-safety mutex

我遇到了一个罕见的程序崩溃,我相信(我很确定)正在调整跨线程访问的向量。我在后推功能中添加了一个互斥锁(下图)。我想我可能会看到一些情况,导致在另一个线程X中调整向量的大小,而线程Y试图从其中一个向量成员复制一个值 - 这导致复制的大小为0,后来导致std :: out_of_range访问。

class TvectorPM {
public:
    pthread_mutex_t lock;
    std::vector<PopulationMember> v;

    TvectorPM();
    virtual ~TvectorPM();

    void add(PopulationMember p);
};

void TvectorPM::add(PopulationMember p) {
    pthread_mutex_lock(&lock);

    v.push_back(p);
    pthread_mutex_unlock(&lock);
}

我并不热衷于为矢量读取添加互斥锁,因为代码中的大多数位置只需要读取,性能是此软件的一个大问题。下面是一个虚假的例子

void EvolutionManager::mutateSingleNode(int num_needed, int pool_size) {
#pragma omp parallel
    {
#pragma omp for schedule(dynamic) nowait
        for (int x = 0; x < num_needed; x ++) {
            // Copy the original RPN Vec, create a new member
            int rand_member = tornament(pool_size);
            PopulationMember p;
            p.rpn_node_vec = population_manager.populationlist.v.at(rand_member).rpn_node_vec;
            p.change();
            population_manager.populationlist.add(p);
        }
    }
}

在我看来,我可以

a) - 获取性能命中和互斥读取

b) - 检查p.rpn_node_vec的大小是否> 0或重读(再次表现一些性能,和hacky)

c) - 在开始循环之前,如果有办法为矢量分配额外的内存以避免需要调整大小,请问好人们。

1 个答案:

答案 0 :(得分:2)

如果要为矢量预先分配内存,可以采用以下几种方法:

// constructor parameter, creates 100 default constructed objects
// giving v1.size() == 100;
std::vector<int> v1(100);

std::vector<int> v2;

// resize() will actually resize the vector making size match the parameter passed in
v2.resize(100);

// again, v2.size() == 100;

std::vector<int> v3;

// reserve just "sets aside" memory for the vector to use later
v3.reserve(100);

// now, v3.size() == 0, but v3.capacity() == 100