is < vector > threadsafe for read/write at different locations? - c++

this is a beginner question i guess but i couldn't find the answer to this particular question:
i have a standard (c++) vector v of size 10 and type int.
is it safe to have a thread alter all the even positions (v.at(0) = x; v.at(2) = y; etc.)
and another thread alter all the values for the odd positions (v.at(1) = a; v.at(3)=b;etc.) at the same time?
so, no changing of size, no push_back() etc. during the lifetime of these 2 threads.
if it is not safe, would the use of an array be a better way to do this?
thanks for your help.

vector does not provide any thread-safety guarantees, so technically the answer would be no.
In practice, you should be able to get away with it... until the day that someone (possibly you) makes a small change in one corner of the program and all hell breaks loose. I wouldn't feel comfortable doing this in any non-trivial program.

From MSDN: Thread Safety in the Standard C++ Library
For reads to the same object, the object is thread safe for reading:
From one thread at a time when no writers on other threads.
From many threads at a time when no writers on other threads.
For writes to the same object, the object is thread safe for writing from one thread when no readers on other threads
For reads to different objects of the same class, the object is thread safe for reading:
From one thread at a time.
From one thread at a time when no writers on other threads.
From many threads at a time.
From many threads at a time when no writers on other threads.
For writes to different objects of the same class, the object is thread safe for writing:
From one thread when no readers on other threads.
From many threads.
So from the above, Theorotically, NO, it won't be threadsafe.

Theoretically: No.
Practically: Yes (According how all well known STLs are implemented)

It's machine-dependent. If you have a vector<char> the processor might not be able to load v[i] and v[i+1] in separate words. You may have cache consistency problems.
Both the compiler and processor might re-order instructions, which can break your program even if the above doesn't apply. This is why C++0x has a memory model.

The scenario you describe will be tread-safe - you effectively manipulate individual elements of a fixed size array (since vector size will not change during those operations), so you don't need any additional synchronization in the first place unless you manipulate any element from more than one thread (which is not you case).

Related

C++ Are plain old array/vector/unordered_map thread safe when no resize/rehash happen? [duplicate]

So I am making some parallel code using OpenMP (but this question should be reasonably applicable to other frameworks), in which I have an array of objects:
std::vector<Body> bodies;
And then I do a little parallel loop to do some things to the bodies. At the start of this parallel section, a team of threads is set up to execute the loop individually. The loop basically uses the values of foo on every Body (apart from the one in question) to update the value of bar on the body in question. So essentially no writes are being done to the values of foo on each body, and the only reads being done on bar are localised to the thread controlling that particular body; in pseudocode, it looks like this:
//create team of threads, and then this section is executed by each thread separately
for each Body i
for each Body j =/= i
i.bar += (j.foo * 2);
end for
end for
My question is whether this will, as I think it should, maintain the coherency of the cache? Because as far as I see it, none of the threads are reaching for things that are being edited by the other threads, so it should be safe, I feel. But This is quite an important point in the report that I need to write on this, so I want to be sure.
Thank you.
The rule is you need synchronization if you have more than one thread and at least one of them is a writer and the threads are accessing the same object. If all of your threads are reading then you do not need any synchronization at all.
With an array/vector if you are writing to it but each thread is writing to its own unique section then you do not need any synchronization either as you are not accessing the same underlying objects (as long as you are not modifying the vector itself like adding or removing elements). The only hazard with this is false sharing. If two threads are working on the different parts of the array but they happen to be on the same cache line then any modification is going to dirty the cache line and both threads will be impacted. This is just a performance impact though and does not lead to undefined behavior.

Thread safety std::array [duplicate]

Lets say I have a vector of int which I've prefilled with 100 elements with a value of 0.
Then I create 2 threads and tell the first thread to fill elements 0 to 49 with numbers, then tell thread 2 to fill elements 50 to 99 with numbers. Can this be done? Otherwise, what's the best way of achieving this?
Thanks
Yes, this should be fine. As long as you can guarantee that different threads won't modify the same memory location, there's no problem.
Yes, for most implementations of vector, this should be ok to do. That said, this will have very poor performance on most systems, unless you have a very large number of elements and you are accessing elements that are far apart from each other so that they don't live on the same cache line... otherwise, on many systems, the two threads will invalidate each other's caches back-and-forth (if you are frequently reading/writing to those elements), leading to lots of cache misses in both threads.
Since C++11:
Different elements in the same container can be modified concurrently
by different threads, except for the elements of std::vector< bool>
(for example, a vector of std::future objects can be receiving values
from multiple threads).
cppreference discusses the thread safety of containers here in good detail.
Link was found in a Quora post.
The fact that "vector is not thread-safe" doesn't mean anything.
There's no problem with doing this.
Also you don't have to allocate your vector on heap (as one of the answers suggested). You just have to ensure that the lifetime of your vector covers the lifetime of your threads (more precisely - where those threads access the vector).
And, of course, since you want your both threads to work on the same vector - they must receive it from somewhere by pointer/reference rather than by value.
There's also absolutely no problem to access the same element of the array from within different threads. You should know however that your thread is not the only one that accesses it, and treat it respectively.
In simple words - there's no problem to access an array from within different threads.
Accessing the same element from different thread is like accessing a single variable from different thread - same precautions/consequences.
The only situation you have to worry about is when new elements are added, which is impossible in your case.
There is no reason why this cannot be done. But, as soon as you start mixing accesses (both threads accessing the same element) it becomes far more challenging.
vector is not thread safe. You need to guard the vector between threads. In your case it depends on vector implementation. If the vector internal data is accessed\modified from different threads, it purely depends on vector impl.
With arrays it can be done for sure (the threads do not access the same memory area); but as already noted, if you use the std::vector class, the result may depend on how it is implemented. Indeed I don't see how the implementation of [] on the vector class can be thread unsafe (provided the threads try to access different "indexes"), but it could be.
The solution is: stick to the use of an array, or control the access to the vector using a semaphore or similar.
What you describe is quite possible, and should word just fine.
Note, however, that the threads will need to work on a std::vector*, i.e. a pointer to the original vector---and you probably should allocate the vector on the heap, rather than the stack. If you pass the vector directly, the copy constructor will be invoked and create a separate copy of the data on each thread.
There are also lots of more subtle ways to get this wrong, as always with multithreaded programming. But in principle what you described will work well.
This should be fine, but you would end up with poor performance due to false sharing where each thread can potentially invalidate each other's cache line

Is it necessary to lock an array that is *only written to* from one thread and *only read from* another?

I have two threads running. They share an array. One of the threads adds new elements to the array (and removes them) and the other uses this array (read operations only).
Is it necessary for me to lock the array before I add/remove to/from it or read from it?
Further details:
I will need to keep iterating over the entire array in the other thread. No write operations over there as previously mentioned. "Just scanning something like a fixed-size circular buffer"
The easy thing to do in such cases is to use a lock. However locks can be very slow. I did not want to use locks if their use can be avoided. Also, as it came out from the discussions, it might not be necessary (it actually isn't) to lock all operations on the array. Just locking the management of an iterator for the array (count variable that will be used by the other thread) is enough
I don't think the question is "too broad". If it still comes out to be so, please let me know. I know the question isn't perfect. I had to combine at least 3 answers in order to be able to solve the question - which suggests most people were not able to fully understand all the issues and were forced to do some guess work. But most of it came out through the comments which I have tried to incorporate in the question. The answers helped me solve my problem quite objectively and I think the answers provided here are quite a helpful resource for someone starting out with multithreading.
If two threads perform an operation on the same memory location, and at least one operation is a write operation, you have a so-called data race. According to C11 and C++11, the behaviour of programs with data races is undefined.
So, you have to use some kind of synchronization mechanism, for example:
std::atomic
std::mutex
If you are writing and reading from the same location from multiple threads you will need to to perform locking or use atomics. We can see this by looking at the C11 draft standard(The C++11 standard looks almost identical, the equivalent section would be 1.10) says the following in section 5.1.2.4 Multi-threaded executions and data races:
Two expression evaluations conflict if one of them modifies a memory
location and the other one reads or modifies the same memory location.
and:
The execution of a program contains a data race if it contains two
conflicting actions in different threads, at least one of which is not
atomic, and neither happens before the other. Any such data race
results in undefined behavior.
and:
Compiler transformations that introduce assignments to a potentially
shared memory location that would not be modified by the abstract
machine are generally precluded by this standard, since such an
assignment might overwrite another assignment by a different thread in
cases in which an abstract machine execution would not have
encountered a data race. This includes implementations of data member
assignment that overwrite adjacent members in separate memory
locations. We also generally preclude reordering of atomic loads in
cases in which the atomics in question may alias, since this may
violate the "visible sequence" rules.
If you were just adding data to the array then in the C++ world a std::atomic index would be sufficient since you can add more elements and then atomically increment the index. But since you want to grow and shrink the array then you will need to use a mutex, in the C++ world std::lock_guard would be a typical choice.
To answer your question: maybe.
Simply put, the way that the question is framed doesn't provide enough information about whether or not a lock is required.
In most standard use cases, the answer would be yes. And most of the answers here are covering that case pretty well.
I'll cover the other case.
When would you not need a lock given the information you have provided?
There are some other questions here that would help better define whether you need a lock, whether you can use a lock-free synchronization method, or whether or not you can get away with no explicit synchronization.
Will writing data ever be non-atomic? Meaning, will writing data ever result in "torn data"? If your data is a single 32 bit value on an x86 system, and your data is aligned, then you would have a case where writing your data is already atomic. It's safe to assume that if your data is of any size larger than the size of a pointer (4 bytes on x86, 8 on x64), then your writes cannot be atomic without a lock.
Will the size of your array ever change in a way that requires reallocation? If your reader is walking through your data, will the data suddenly be "gone" (memory has been "delete"d)? Unless your reader takes this into account (unlikely), you'll need a lock if reallocation is possible.
When you write data to your array, is it ok if the reader "sees" old data?
If your data can be written atomically, your array won't suddenly not be there, and it's ok for the reader to see old data... then you won't need a lock. Even with those conditions being met, it would be appropriate to use the built in atomic functions for reading and storing. But, that's a case where you wouldn't need a lock :)
Probably safest to use a lock since you were unsure enough to ask this question. But, if you want to play around with the edge case of where you don't need a lock... there you go :)
One of the threads adds new elements to the array [...] and the other [reads] this array
In order to add and remove elements to/from an array, you will need an index that specifies the last place of the array where the valid data is stored. Such index is necessary, because arrays cannot be resized without potential reallocation (which is a different story altogether). You may also need a second index to mark the initial location from which the reading is allowed.
If you have an index or two like this, and assuming that you never re-allocate the array, it is not necessary to lock when you write to the array itself, as long as you lock the writes of valid indexes.
int lastValid = 0;
int shared[MAX];
...
int count = toAddCount;
// Add the new data
for (int i = lastValid ; count != 0 ; count--, i++) {
shared[i] = new_data(...);
}
// Lock a mutex before modifying lastValid
// You need to use the same mutex to protect the read of lastValid variable
lock_mutex(lastValid_mutex);
lastValid += toAddCount;
unlock_mutex(lastValid_mutex);
The reason this works is that when you perform writes to shared[] outside the locked region, the reader does not "look" past the lastValid index. Once the writing is complete, you lock the mutex, which normally causes a flush of the CPU cache, so the writes to shared[] would be complete before the reader is allowed to see the data.
Lock? No. But you do need some synchronization mechanism.
What you're describing sounds an awful like a "SPSC" (Single Producer Single Consumer) queue, of which there are tons of lockfree implementations out there including one in the Boost.Lockfree
The general way these work is that underneath the covers you have a circular buffer containing your objects and an index. The writer knows the last index it wrote to, and if it needs to write new data it (1) writes to the next slot, (2) updates the index by setting the index to the previous slot + 1, and then (3) signals the reader. The reader then reads until it hits an index that doesn't contain the index it expects and waits for the next signal. Deletes are implicit since new items in the buffer overwrite previous ones.
You need a way to atomically update the index, which is provided by atomic<> and has direct hardware support. You need a way for a writer to signal the reader. You also might need memory fences depending on the platform s.t. (1-3) occur in order. You don't need anything as heavy as a lock.
"Classical" POSIX would indeed need a lock for such a situation, but this is overkill. You just have to ensure that the reads and writes are atomic. C and C++ have that in the language since their 2011 versions of their standards. Compilers start to implement it, at least the latest versions of Clang and GCC have it.
It depends. One situation where it could be bad is if you are removing an item in one thread then reading the last item by its index in your read thread. That read thread would throw an OOB error.
As far as I know, this is exactly the usecase for a lock. Two threads which access one array concurrently must ensure that one thread is ready with its work.
Thread B might read unfinished data if thread A did not finish work.
If it's a fixed-size array, and you don't need to communicate anything extra like indices written/updated, then you can avoid mutual exclusion with the caveat that the reader may see:
no updates at all
If your memory ordering is relaxed enough that this happens, you need a store fence in the writer and a load fence in the consumer to fix it
partial writes
if the stored type is not atomic on your platform (int generally should be)
or your values are un-aligned, and especially if they may span cache lines
This is all dependent on your platform though - hardware, OS and compiler can all affect it. You haven't told us what they are.
The portable C++11 solution is to use an array of atomic<int>. You still need to decide what memory ordering constraints you require, and what that means for correctness and performance on your platform.
If you use e.g. vector for your array (so that it can dynamically grow), then reallocation may occur during the writes, you lose.
If you use data entries larger than is always written and read atomically (virtually any complex data type), you lose.
If the compiler / optimizer decides to keep certain things in registers (such as the counter holding the number of valid entries in the array) during some operations, you lose.
Or even if the compiler / optimizer decides to switch order of execution for your array element assignments and counter increments/decrements, you lose.
So you certianly do need some sort of synchronization. What is the best way to do so (for example it may be worth while to lock only parts of the array), depends on your specifics (how often and in what pattern do the threads access the array).

Can you avoid locking by guaranteeing that multiple threads won't access the same memory?

Say I have a large array and I want to process the contents with multiple threads. If I delegate each thread to a specific section, guaranteeing no overlap, does that eliminate any need for locking, assuming the threads don't access any other memory outside the array?
Something like this (pseudo-code):
global array[9000000];
do_something(chunk) {
for (i = chunk.start; i < chunk.end; i++)
//do something with array
}
main() {
chunk1 = {start: 0, end: 5000000};
chunk2 = {start: 5000000, end: 9000000};
start_thread(thread1, do_something(chunk1));
start_thread(thread2, do_something(chunk2));
wait_for_join(thread1);
wait_for_join(thread2);
//do something else with the altered array
}
In a conforming C++11 compiler this is safe [intro.memory] (§1.7):
A memory location is either an object of scalar type or a maximal
sequence of adjacent bit-fields all having non-zero width. [...] Two
threads of execution (1.10) can update and access separate memory
locations without interfering with each other.
C11 gives identical guarantees (they even use the same wording) in §3.14.
In a C++03 compiler this is not guaranteed to work by the standard, but it might still work if the compiler provides similar guarantees as an extension.
Yes: if you can guarantee that no two threads will access the same element, then there's no need for any further synchronisation.
There is only a conflict (and therefore a potential data race) if two threads access the same memory location (with at least one of them modifying it) without synchronisation.
(NOTE: this answer is based on the C++11 memory model. I've just noticed that you're also asking about a second language; I believe that C11 specifies a very similar memory model, but can't say for sure that the answer is also valid for C. For older versions of both languages, thread-safety was implementation-dependent.)
Yes, you can indeed.
TCMalloc is a good example.
Yes.
You do not even need to guarantee that no two threads access the same memory location. All you need to guarantee is that no single thread modifies any location that another one accesses (regardless whether that means reading or writing).
Given either no concurrent access at all or read-only concurrent access, you're good to go without locking.
Important performance issue !
Right, you doesn't need explicit locking, since, as said by others, no memory location is shared.
But you may trigger implicit hardware synchronization, since arbitrary chunks are likely to lead cache lines to be shared (not much with the figures used in your example, though). It is known as false sharing.
Higher level approach such as OpenMP resolves these kinds of issue :
chunks alignment (and threads numbers) are tuned according to underlying hardware.
it provides a better control over pool of threads, eg amortizing the cost of thread instantiations.
it's easier to write, and actually less intrusive.

Can multiple threads access a vector at different places?

Lets say I have a vector of int which I've prefilled with 100 elements with a value of 0.
Then I create 2 threads and tell the first thread to fill elements 0 to 49 with numbers, then tell thread 2 to fill elements 50 to 99 with numbers. Can this be done? Otherwise, what's the best way of achieving this?
Thanks
Yes, this should be fine. As long as you can guarantee that different threads won't modify the same memory location, there's no problem.
Yes, for most implementations of vector, this should be ok to do. That said, this will have very poor performance on most systems, unless you have a very large number of elements and you are accessing elements that are far apart from each other so that they don't live on the same cache line... otherwise, on many systems, the two threads will invalidate each other's caches back-and-forth (if you are frequently reading/writing to those elements), leading to lots of cache misses in both threads.
Since C++11:
Different elements in the same container can be modified concurrently
by different threads, except for the elements of std::vector< bool>
(for example, a vector of std::future objects can be receiving values
from multiple threads).
cppreference discusses the thread safety of containers here in good detail.
Link was found in a Quora post.
The fact that "vector is not thread-safe" doesn't mean anything.
There's no problem with doing this.
Also you don't have to allocate your vector on heap (as one of the answers suggested). You just have to ensure that the lifetime of your vector covers the lifetime of your threads (more precisely - where those threads access the vector).
And, of course, since you want your both threads to work on the same vector - they must receive it from somewhere by pointer/reference rather than by value.
There's also absolutely no problem to access the same element of the array from within different threads. You should know however that your thread is not the only one that accesses it, and treat it respectively.
In simple words - there's no problem to access an array from within different threads.
Accessing the same element from different thread is like accessing a single variable from different thread - same precautions/consequences.
The only situation you have to worry about is when new elements are added, which is impossible in your case.
There is no reason why this cannot be done. But, as soon as you start mixing accesses (both threads accessing the same element) it becomes far more challenging.
vector is not thread safe. You need to guard the vector between threads. In your case it depends on vector implementation. If the vector internal data is accessed\modified from different threads, it purely depends on vector impl.
With arrays it can be done for sure (the threads do not access the same memory area); but as already noted, if you use the std::vector class, the result may depend on how it is implemented. Indeed I don't see how the implementation of [] on the vector class can be thread unsafe (provided the threads try to access different "indexes"), but it could be.
The solution is: stick to the use of an array, or control the access to the vector using a semaphore or similar.
What you describe is quite possible, and should word just fine.
Note, however, that the threads will need to work on a std::vector*, i.e. a pointer to the original vector---and you probably should allocate the vector on the heap, rather than the stack. If you pass the vector directly, the copy constructor will be invoked and create a separate copy of the data on each thread.
There are also lots of more subtle ways to get this wrong, as always with multithreaded programming. But in principle what you described will work well.
This should be fine, but you would end up with poor performance due to false sharing where each thread can potentially invalidate each other's cache line