Take the 2-minute tour ×

Possible Duplicate:
STL vector and thread-safety

A simple example:

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

Suppose, v is shared in thread-1, and thread-2. v.set_a() is always called in thread-1 and v.push_back() in thread-2. So there is no issue of thread-safety.

What happens for below sequence of events:

  1. The thread-1 calls v.set_a()
  2. Before line-3, thread-2 resizes the vector (push_back(), resize(),...)
  3. Not enough contiguous memory at current location and v has to be moved to other location

Will it lead to undefined behavior ? If yes, then what is the most elegant solution for such scenario ?

share|improve this question

marked as duplicate by jogojapan, juanchopanza, Bo Persson, Christian Rau, kapa Jul 5 '12 at 8:35


Asked the other way around, what made you assume that this might actually work? you are modifying an object that is completely unaware of threads in one thread and use it in another at the same time. Whenever you do this, synchronize properly using the usual means, nothing different for a vector. Since you talk about multithreading you are of course aware of the basic means for thread synchronization. –  Christian Rau Jul 5 '12 at 7:43

2 Answers 2

up vote 2 down vote accepted

The standard (C++11, and previously Posix) is very clear about this. You are modifying an object (the vector) in one thread, and accessing it from more that one thread, so all accesses, including read accesses, must be protected. (At least I suppose. v.set_a() isn't a legal expression if v has type std::vector<A>; I'm guessing that you mean v[i].set_a(), or something similar.)

I'm not sure about the exact wording of the standard(s) here, but I would assume that "modifying the vector" only means operations which change its size, and not operations which modify a single member. So things like v[0] = x in one thread, and v[1] in another, are legal without synchronization. But all accesses to any object in the vector, are accesses to the vector, so if there is a change in the size of the vector, all accesses to objects in the vector must be protected. This includes "deferred" accesses because you've saved a reference returned by v[]: given something like:

int& ri = v[i];
//  ...

the entire block of code must be protected if any thread is modifying the vector.

share|improve this answer

There is nothing to say that vector resizing is thread-safe, so one must assume it isn't. In your example I would certainly expect problems, since you rely on many non-atomic operations. An elegant solution would be to simply wrap it in a thread-safe version.

share|improve this answer
std::vector is thread-safe, in the sense that it documents (more or less) exactly what rules have to be respected when using it in a multithreaded environment. Adding further thread safety inside of std::vector is a loosing battle. Since many of the functions return references to internal data, the accesses you have to protect occur outside of the class and its member functions. –  James Kanze Jul 5 '12 at 7:29
@JamesKanze good point about the references. One cannot just wrap it and export the same interface. –  juanchopanza Jul 5 '12 at 7:38
No, although I've seen people who tried. (It cost us a lot of time cleaning up afterwards, since we had to find all uses in the code base.) I'm not sure it's worth doing even if you could; in my experience, the granularity of the protection is too fine if it is in a class like vector. Most of the time, you'll need locks at a higher level anyway. –  James Kanze Jul 5 '12 at 7:44
