Is changing address of pointer always atomic operation? is it safe to change pointer = NULL to some value(address) under multithread application?
more info:
There is std::map<int, SomePointer*. I access map with find() with locked mutex for READING. I get iterator to some element and then I want to change iterator->second (in another words SomePointer*)
So, while mutex of map locked for reading, map will not changed at this time. Only other readers will have access to the map. So, for me it's fine if other readers will get old value NULL or NEW ADDRESS... but, of course, I fear that some thread will access to some average state and get corrupted address. So, is it safe to change iterator->second under read mutex?
No, changing the value of anything that isn't explicitly made thread safe is not thread safe.
If you wish to perform possibly-concurrent writes and reads to/from a pointer without a data race or a lock, use a std::atomic.
Related
I have an unordered_map and I'm using mutex locks for emplace and delete, find operations, but I don't use a mutex when modifying map's elements, because I don't see any point. but I'm curious whether I'm wrong in this case.
Should I use one when modifying element value?
std::unordred_map<std::string, Connection> connections;
// Lock at Try_Emplace
connectionsMapMutex.lock();
auto [element, inserted] = connections.try_emplace(peer);
connectionsMapMutex.unlock();
// No locks here from now
auto& connection = element->second;
// Modifying Element
connection.foo = "bar";
Consider what can happen when you have one thread reading from the map and the other one writing to it:
Thread A starts executing the command string myLocalStr = element->second.foo;
As part of the above, the std::string copy-constructor starts executing: it stores foo's character-buffer-pointer into a register, and starts dereferencing it to copy out characters from the original string's buffer to myLocalStr's buffer.
Just then, thread A's quantum expires, and thread B gains control of the CPU and executes the command connection.foo = "some other string"
Thread B's assignment-operator causes the std::string to deallocate its character-buffer and allocate a new one to hold the new string.
Thread A then starts running again, and continues executing the std::string copy-constructor from step 2, but now the pointer it is dereferencing to read in characters is no longer pointing at valid data, because Thread A deleted the buffer! Poof, Undefined Behavior is invoked, resulting in a crash (if you're lucky) or insidious data corruption (if you're unlucky, in which case you'll be spending several weeks trying to figure out why your program's data gets randomly corrupted only about once a month).
And note that the above scenario is just on a single-core CPU; on a multicore system there are even more ways for unsynchronized accesses to go wrong, since the CPUs have to co-ordinate their local and shared memory-caches correctly, which they won't know to do if there is no synchronization code included.
To sum up: Neither std::unordered_map nor std::string are designed for unsynchronized multithreaded access, and if you try to get away with it you're likely to regret it later on.
Here's what I would do, if and only if I'm threading and there's a chance other threads are manipulating the list and its contents.
I would create a mutex lock when manipulating the list (which you've done) or when traversing the list.
And if I felt it was necessary to protect an individual item in the list (you're calling methods on it), I'd give each one a distinct mutex. You could change element A and element B simultaneously and it's fine, but by using the local locks for each item, each is safe.
However, it's very rare I've had to be that careful.
As I understand a data race can only occur with a std::vector when one or more threads are modifying a vector. If all threads are simply reading that is thread-safe.
Now assume I have 2 threads. One which can only read from the vector, but the other reads and modifies the size of the vector. I have a lock to remain thread-safe to the vector.
When the read-only thread reads from the vector it must use the lock since it does not know what the other thread is doing at the same time.
However, the read and write thread knows that the read-only thread is read-only and thus when it is reading the other thread can only be reading or not. This means that a data-race is impossible in that case and it does not have to use the lock.
The read and write thread must still use the lock when modifying the vector.
Is that right?
You are correct. If your single writer thread is in read mode, then a lock does not need to happen because the other thread is only a reader. Readers can't conflict with each other. The read only thread will still need to acquire the lock on every read, and the writing thread will need to lock when it writes, but it doesn't need to lock to read.
So i have multiple threads accessing this function to retrieve database information, is it thread safe?
vector<vector<string> > Database::query(const char* query)
{
pthread_rwlock_wrlock(&mylock); //Write-lock
...
vector<vector<string> > results;
results.push...
pthread_rwlock_unlock(&mylock); //Write-lock
return results;
}
for editors -> sometimes 'fixing' > > to >> is not a good idea but thanks for the rest.
Since results is a local variable, it is in itself safe to use without locks, since there will be a unique copy per thread (it is on the stack, the contents of the vector dynamically allocated in some way, etc). So as long as your database is thread safe, you don't need any locks at all. If the DB is not threadsafe, you need to protect that, of course.
As noted in the other answer, if, for some reason, for example the creation of a string causes a throw bad_alloc;, you need to deal with the fallout of that, and make sure the lock is unlocked (unless you really wish to deadlock all other threads!)
Generally speaking, multiple threads can hold "read" locks. Only one thread can hold "write" lock. And no "read" locks might be held while there is a "write" lock.
It means that while mylock is held locked inside query method, no-one else can have it locked for either read or write, so it is thread-safe. You can read more about readers-writer lock here. Whether you need that mutex locked in there or not is another question.
The code is not exception-safe, however. You must employ RAII in order to unlock a mutex automatically, including on stack unwinding.
It is thread safe because results is created as a local variable, so only one thread will ever access it any instance of results within this method.
If you need a thread-safe vector for some other reason, see this answer on Threadsafe Vector Class for C++.
In my program I've some threads running. Each thread gets a pointer to some object (in my program - vector). And each thread modifies the vector.
And sometimes my program fails with a segm-fault. I thought it occurred because thread A begins doing something with the vector while thread B hasn't finished operating with it? Can it be true?
How am I supposed to fix it? Thread synchronization? Or maybe make a flag VectorIsInUse and set this flag to true while operating with it?
vector, like all STL containers, is not thread-safe. You have to explicitly manage the synchronization yourself. A std::mutex or boost::mutex could be use to synchronize access to the vector.
Do not use a flag as this is not thread-safe:
Thread A checks value of isInUse flag and it is false
Thread A is suspended
Thread B checks value of isInUse flag and it is false
Thread B sets isInUse to true
Thread B is suspended
Thread A is resumed
Thread A still thinks isInUse is false and sets it true
Thread A and Thread B now both have access to the vector
Note that each thread will have to lock the vector for the entire time it needs to use it. This includes modifying the vector and using the vector's iterators as iterators can become invalidated if the element they refer to is erase() or the vector undergoes an internal reallocation. For example do not:
mtx.lock();
std::vector<std::string>::iterator i = the_vector.begin();
mtx.unlock();
// 'i' can become invalid if the `vector` is modified.
If you want a container that is safe to use from many threads, you need to use a container that is explicitly designed for the purpose. The interface of the Standard containers is not designed for concurrent mutation or any kind of concurrency, and you cannot just throw a lock at the problem.
You need something like TBB or PPL which has concurrent_vector in it.
That's why pretty much every class library that offers threads also has synchronization primitives such as mutexes/locks. You need to setup one of these, and aquire/release the lock around every operation on the shared item (read AND write operations, since you need to prevent reads from occuring during a write too, not just preventing multiple writes happening concurrently).
I have question regarding thread safety as below ( I have only two threads in which one of the threads only read from the map, the other threads would be writing and reading as shown):
//Thread 2: the reading and writing thread
unordered_map<int, unordered_map<classA*>*>testMap;
//need lock because writing to the map?
testMap[1] = new unordered_map<int, classA*>;
//do not need lock because only reading and the other thread is only reading?
unordered_map<classA*>* ptr = testMap[1];
//need lock because writing?
(*ptr)[1] = new classA;
//do not need lock because only reading and the other thread is only reading?
classA* ptr2 = (*ptr)[1];
//din't modify the map, but modify the data pointed by the pointer stored by the map, do I need lock?
ptr2->field1 = 5;
ptr2->field2 = 6;
//end of reading and writing thread
What is the correct way to lock to unordered_map? Also, should I use a single lock or multiple locks?
Thanks.
If your map is the only shared resource, a single mutex is sufficient.
You need to lock the writing in the first thread, and lock the reading in the second one. If you lock the map only when writing on it, the second thread could read it while you are writing in it.
You dont need a lock in the last example regarding the pointers, since you dont deal with any data stored in the map.
Edit : in fact, it depends on what your are doing with the pointers and in which thread you do it.
You should read this great article : http://herbsutter.com/2010/09/24/effective-concurrency-know-when-to-use-an-active-object-instead-of-a-mutex/
You need to lock both, reading and writing. If you do not lock reading then a write can occur while you are reading and you may access the map in an inconsistent state.
What would be best in your situation would be a reader-writer-lock. Such a lock allows multiple readers to read at the same time but only one writer at the same time and no readers while a writer writes and vice versa.
Couple of things:
You should consider smart pointers to store in your map.
What you are doing is potentially quite dangerous (i.e. you may not be modifying the main map), but you are modifying what's stored there and if you do this outside of a lock, the end result could be anything - let's say that thread one has also read the same pointer and starts iterating whilst thread two is writing the instance of classA - what happens then?
I would have a lock around the main map, and then another lock for each payload map. Any operations on either map should require to obtain the lock at the correct level. I'd also be careful not to return iterators outside of the class that manages the lock, so basically you should implement all the methods you'd need within the class.