I'm having a function that needs to be executed n=1000
times. This functions does a Monte Carlo style simulation and returns an int
as the result. I'd like to run nthreads=4
in parallel. Whenever a thread finishes one cycle, it should put the result in a std::vector<int>
. Thus, after 1000 cycles, I've a vector of 1000 int
s that can be examined by statistics.
Since a std::vector
is not thread-safe, I thought about std::mutex
(which would surely work).
But I wonder if I can declare a vector to be atomic and thus get around mutexes? Is it possible to have a std::atomic<std::vector<int>>
? And can I use push_back
etc. on it?
const and Thread Safety Therefore all classes available from the standard, e.g. std::vector<>, can safely be accessed from multiple threads in the same manner.
Yes, it would be threadsafe. Assuming of course there are no bugs in the std::atomic implementation - but it's not usually hard to get right. This is exactly what std::atomic is meant to do.
In order to solve this problem, C++ offers atomic variables that are thread-safe. The atomic type is implemented using mutex locks. If one thread acquires the mutex lock, then no other thread can acquire it until it is released by that particular thread.
Yes, you are right. I obviously misunderstood that sentence in the documentation: "No contained elements are accessed: concurrently accessing or modifying them is safe." It probably only means that size() is thread-safe against a concurrent modification of the elements already in the container.
C++11 §29.5/1 says
There is a generic class template atomic. The type of the template argument T shall be trivially copyable (3.9).
What does trivially copyable mean?
§3.9 tells
Scalar types, trivially copyable class types (Clause 9), arrays of such types, and cv-qualified versions of these types (3.9.3) are collectively called trivially copyable types.
For class types (of which std::vector
is):
A trivially copyable class is a class that:
- has no non-trivial copy constructors
- has no non-trivial move constructors
- has no non-trivial copy assignment operators
- has no non-trivial move assignment operators
- has a trivial destructor
According to this list std::vector
is not trivially copyable and so you cannot use std::atomic<std::vector<int>>
.
Since you know the size in advance and since you do not need to use methods that would require the vector be reallocated in a different location (like push_back)
. You can use std::vector<int>::resize
or the size constructor to preallocate and preconstruct the required int
s. Therefore your concurrent threads do not need to operate on the vector itself but on the elements.
If there is no access from different threads to the same element there is no race condition.
The same goes for int k[1000]
which is trivially copyable. But you do not need it to be since the threads do not change the array/vector/list itself but the elements.
You don't need to. It is totally okay to access a std::vector
from multiple threads, if
So just make sure, you create a vector of size n=1000
and depending on your thread number (1 to 4) you assign elements 0-249, 250-499 etc. to your threads.
So each of your thread computes n/nthreads
elements.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With