concurrent_vector thread safety

concurrent_vector thread safety

Kevin Farnham's picture

On the #tbb channel, the question of what concurrent access is possible using the concurrent_vector container was discussed.

I would think that there is no problem with multiple threads reading from the same concurrent_vector container. It also looks like (from reading the TBB Reference manual) multiple threads can safely perform many "write" operations on a concurrent_vector container (but whole vector operations are not thread safe).

The users on the #tbb channel were wondering about internal counters, etc., trying to decide when it's necessary to use a concurrent_vector instead of using the STL vector, and what exact level of thread safety is gained through concurrent_vector.

Does anyone have additional comments on concurrent_vector and thread safety?

3 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
Arch D. Robison (Intel)'s picture

tbb::concurrent_vector allows multiple threads to grow and access the vector at the same time. This is the level of thread safety that tbb_concurrent_vector has over std::vector. Simultaneously growing and accessing elements is a recurring idiom in parallel programming.

For example, if x is a std::vector and thread #1 executes x.resize(x.size()+1) while thread #2 executes x[0]=...; internal corruption may result, because in typical implementations of std::vector, a resize operation may cause the internal storage to move to a different address. Thus the location of x[0] in memory may move between the time that the reference to x[0] is computed and x[0] is assigned to.

tbb::concurrent_vector deals with the problem by not moving existing storage when resizing. Instead, in order to grow, it creates a new chunk of storage. The chunks are accessed by a fast constant-time indexing scheme. See tbb/concurrent_vector.h for how it is implemented.

However, there is no free lunch here. The concurrent_vector indexing introduces an extra level of complexity compared to std::vector. So if you do not need to concurrently grow and access a vector, I recommend using std::vector. But if you do have multiple threads appending to a dynamically growing array, then concurrent_vector can be a good fit.

concurrent_vector allows multiple threads to access (read, write, take the address) of the same element. It does not serialize the accesses, so whether those accesses are safe depends upon the data type.

Kevin Farnham's picture

Thanks for the detailed description. That clarifies a lot.

Login to leave a comment.