在线程上的2D向量上push_back是安全的吗?

时间:2012-11-06 10:54:28

标签: c++ multithreading boost vector

假设我有一个2D数组和这个函数:

void addVec(std::vector<std::vector<short> >& arr, size_t idx){ 
   arr[idx].push_back(idx);
}

std::vector<std::vector<short> > arr(2);
boost::threads th1(addVec, boost::ref(arr), 0);
boost::threads th2(addVec, booost::ref(arr), 1);
th1.join();
th2.join();

到现在我应该有arr [0] [0] = 0;和arr [1] [0] = 1; 问题是这是否安全? 在内部,线程应该向向量存储器的不同部分添加值,并且因为它是在大小2的开头构造的,所以只有内部向量被调整大小,具有线程独占访问权。

4 个答案:

答案 0 :(得分:4)

这应该是安全的,因为每个线程访问一个单独的向量。但是,如果你做了任何可能导致arr调整大小的事情,那么所有的赌注都会被取消......

答案 1 :(得分:4)

我建议您退后一步,考虑一下您的目标是什么,然后再继续沿着您的目标前进。

首先,您为什么要并行化代码?我假设你希望你的程序运行得更快。这意味着

  1. 您应该首先编写一个有效的顺序实现。
  2. 您应该对该实施进行概述和调整。
  3. 如果(且且仅当)您的程序对于您的目的而言仍然太慢,则应在以下情况下对其进行并行化:
    1. 程序的很大一部分可以并行化(查看Amdahl's law)。
    2. 您的顺序实现充分利用了cache。 即使对于顺序代码,缓存也很可能成为瓶颈,所以如果你的 代码不是缓存有效的,并行化它可能会慢一些。
  4. 要点1.和2.可能就是你应该投入时间的地方。可能的情况是,高度调整的顺序实现已经足以满足您的需求,并且开发和维护将更加便宜/更容易/更快。

    如果您决定并行化代码,则应该查看OpenMP。线程可能是编写人类已知并行程序的最糟糕方法之一。您可能认为OpenMP的运行时系统对您而言太慢了,但您应该退一步思考原因。

    如果您的算法需要大量锁定和障碍,则可以通过使用更快的锁定和障碍来获得较小的加速。如果您将算法改进为使用更少的锁和障碍,则可以实现更大的加速。

答案 2 :(得分:2)

这是安全的,尽管从设计的角度来看,给每个线程只提供其内部向量会更安全,因此未来不安全行为的可能性较小

答案 3 :(得分:2)

是的,在您的使用案例中它是安全的,因为您不会修改共享数据。但是,我更愿意将std::vector<short>的引用传递给每个线程以简化用法:

void addVec(std::vector<short> & arr)
{ 
   arr.push_back(some_data);
}

std::vector<std::vector<short> > arr(2);
boost::threads th1(addVec, boost::ref(arr[0]));
boost::threads th2(addVec, booost::ref(arr[1]));
th1.join();
th2.join();