矢量自动调整多线程代码中的危险情况吗?

时间:2012-07-05 05:50:45

标签: c++ multithreading vector resize undefined-behavior

  

可能重复:
  STL vector and thread-safety

一个简单的例子:

struct A {
  int a;
  void set_a (int x)
  {
    ...  // line-1
    ...  // line-2
    this->a = x;  // line-3
  }
};
...
vector<A> v;  // somewhere

假设,v在thread-1和thread-2中共享。始终在线程1中调用v.set_a(),在线程2中调用v.push_back()。所以没有线程安全问题。

以下事件序列会发生什么:

  1. 线程1调用v.set_a()
  2. 在第3行之前,thread-2调整了向量的大小(push_back()resize(),...)
  3. 当前位置的连续内存不足,v必须 搬到其他地方
  4. 会导致未定义的行为吗?如果是,那么对于这种情况,最优雅的解决方案是什么?

2 个答案:

答案 0 :(得分:3)

没有什么可以说矢量大小调整是线程安全的,所以必须假设它不是。在你的例子中,我肯定会遇到问题,因为你依赖于许多非原子操作。一个优雅的解决方案是简单地将其包装在一个线程安全的版本中。

答案 1 :(得分:2)

标准(C ++ 11,以前的Posix)对此非常清楚。 您正在一个线程中修改一个对象(向量)并访问它 来自更多的一个线程,所以所有访问,包括读取访问, 必须得到保护。 (至少我猜想。v.set_a()不合法 表达式v的类型为std::vector<A>;我猜你的意思是 v[i].set_a(),或类似的东西。)

我不确定这里标准的确切措辞,但是我 会假设“修改矢量”仅表示操作 更改其大小,而不是修改单个成员的操作。所以 一个线程中的v[0] = x和另一个线程中的v[1]之类的内容是合法的 没有同步。但是对向量中任何对象的所有访问, 是访问向量,所以如果有大小的变化 向量,必须保护对向量中对象的所有访问。这个 包括“延迟”访问,因为您已保存返回的引用 通过v[]:给出类似的内容:

int& ri = v[i];
//  ...
doSomethingWithRi(ri);

如果任何线程正在修改,则必须保护整个代码块 矢量。