C ++ 11 std :: vector in a parallel environment

I had a problem (segfault) on which multithreaded code was run in C ++ 11. Here is the code:

#include <vector> #include <thread> std::vector<int> values; int i; void values_push_back() { values.push_back(i); } int main() { while(true) { std::vector<std::thread> threads; for(i=0; i<10; ++i) { std::thread t(values_push_back); threads.push_back(std::move(t)); } for(i=0; i<10; ++i) threads[i].join(); } return 0; } 

And here is the backtrace on gdb: http://pastebin.com/5b5TN70c

What's bad about it?

+7
source share
1 answer

This is not related to moving.

Multiple threads execute vector::push_back() on the same vector , but vector::push_back() not thread safe. Changes to vector must be synchronized.

A std::mutex can be used to synchronize calls with push_back() :

 std::vector<int> values; std::mutex values_mutex; void values_push_back() { values_mutex.lock(); values.push_back(i); values_mutex.unlock(); } 

In addition, the variable i is divided between threads without synchronization, which will lead to a race condition (a possible result of this duplication int added to vector ). Consider passing an int value as an argument to the stream to avoid this:

 std::vector<int> values; std::mutex values_mutex; void values_push_back(int i) { values_mutex.lock(); values.push_back(i); values_mutex.unlock(); } for (int i = 0; i < 10; ++i) { threads.push_back(std::thread(values_push_back, i)); } for (auto& t: threads) t.join(); 

As bamboon pointed out , prefer std::lock_guard to ensure the lock is released if push_back() throws (which in this case can only be bad_alloc() , but if vector changes to hold more complex objects that the constructors throw, it becomes more important):

 void values_push_back(int i) { std::lock_guard<std::mutex> lk(values_mutex); values.push_back(i); } 
+11
source

All Articles