I have an unordered map which stores a pointer of objects. I am not sure whether I am doing the correct thing to maintain the thread safety.
typedef std::unordered_map<string, classA*>MAP1;
MAP1 map1;
pthread_mutex_lock(&mutexA)
if(map1.find(id) != map1.end())
{
pthread_mutex_unlock(&mutexA); //already exist, not adding items
}
else
{
classA* obj1 = new classA;
map1[id] = obj1;
obj1->obtainMutex(); //Should I create a mutex for each object so that I could obtain mutex when I am going to update fields for obj1?
pthread_mutex_unlock(&mutexA); //release mutex for unordered_map so that other threads could access other object
obj1->field1 = 1;
performOperation(obj1); //takes some time
obj1->releaseMutex(); //release mutex after updating obj1
}
Several thoughts.
If you do have one mutex per stored object, then you should try to create that mutex in the constructor for the stored object. In other words, to maintain encapsulation, you should avoid having external code manipulate that mutex. I would convert "field1" into a setter "SetField1" that handles the mutex internally.
Next, I agree with the comment that you could move pthread_mutex_unlock(&mutexA); to occur before obj1->obtainMutex();
Finally, I don't think you need obtainMutex at all. Your code looks as if only one thread will ever be allowed to create an object, and therefore only one thread will manipulate the contents during object creation. So if I consider only what little code you've shown here, it does not seem that mutex-per-object is needed at all.
One problem I see with the code is that it will lead to problems especially when exceptions occur.
obj1->obtainMutex(); //Should I create a mutex for each object so that I could obtain mutex when I am going to update fields for obj1?
pthread_mutex_unlock(&mutexA); //release mutex for unordered_map so that other threads could access other object
obj1->field1 = 1;
performOperation(obj1);
If performOperation throws an exception then obj1->releaseMutex(); will never get called thus leaving the object locked and potentially leading to deadlocks sometime in the future.
And even if you do not use exceptions yourself some library code you use in performOperation might. Or you might mistakenly sometime in the future insert a return and forget to unlock all owned locks before and so on...
The same goes for the pthread_mutex_lock and pthread_mutex_unlock calls.
I would recommend using RAII for locking / unlocking.
I.e. the code could look like this:
typedef std::unordered_map<string, classA*>MAP1;
MAP1 map1;
Lock mapLock(&mutexA); //automatci variable. The destructor of the Lock class
//automatically calls pthread_mutex_unlock in its destructor if it "owns" the
//mutex
if(map1.find(id) == map1.end())
{
classA* obj1 = new classA;
map1[id] = obj1;
Lock objLock(obj);
mapLock.release(); //we explicitly release mapLock here
obj1->field1 = 1;
performOperation(obj1); //takes some time
}
I.e. for a reference for some minimalistic RAAI threading support please refer to "Modern C++ design: generic programming and design patterns applied" by Andrei Alexandrescu (see here). Other resources also exist (here)
I will try to describe in the end one other problem I see with the code. More exactly, the problem I see with having the obtainMutex and releaseMutex as methods and calling them explicitly. Let's imagine thread 1 locks the map, creates an object calls obtainMutex and unlocks the map. Another thread (lets call it Thread 2) gets scheduled for execution locks the map obtains an iterator to the map1[id] of the object and calls releaseMutex() on the pObject (i.e. let's say due to a bug the code does not attempt to call obtainMutex first). Now Thread 1 gets scheduled and calls at some point releaseMutex() also. So the object got locked once but released twice. What I am trying to say is that it's going to be hard work making sure the calls are always correctly paired in the face of exceptions, potential early returns that do not unlock and incorrect usage of the object locking interface. Also Thread 2 might just delete the pObject it obtained from the map and erase it from the map. thread 1 will then go on an work with an already deleted object.
When used judiciously RAII would make the code simpler to understand (even shorter if you compare our versions) and also help a lot with some of the problems I enumerated above.
Thought of combining my comments into an answer:
1) When you are adding an entry, and therefore are modifying the container, you should not allow read access from other threads, as the container may be in a transition between legal states. Complementary, you should not modify the container when other threads are reading it. This calls for the use of read-write lock. The pseudo-code is something like:
set read lock
search container
if found
release read lock
operate on the found object
else
set write lock
release read lock
add entry
release write lock
endif
(it's been some time since I've done multi-threaded programming, so I may be rusty on details)
2) When I worked on MSVC some years ago we used the multi-threaded (i.e. thread-safe) version of the standard libraries. It could save you all this trouble. Didn't bother (yet) to check if thread-safe std exists also on gcc/Linux.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have a global object which is shared by different threads. To provide the synchronization, I have added a mutex inside the global object.
Mutex will locked by a thread before accessing the data inside the object.
Everything is fine except delete.
If a thread is locking the mutex and deleting the object.
How again it can unlock it? (because memory will be released for data and hence mutex)
How can a safe delete be implemented using this approach i.e. keeping mutex inside the object?
Typically, you have a global object like that (using std::mutex as example):
std::mutex theGlobalMutex; // no pointer, no reference!
This way, the object will be initialised before the program starts running, and it will be cleaned up automatically as soon as you are leaving the program (destructor being called is guaranteed by the standard). No problem at all - at first. There are situations when the actual initialisation can be delayed (see e.g. here mentioned somewhere in the middle of the article), but you should be safe from that if you define your global object in the file containing the main function.
Alternative, if you really want to control object creation yourself:
std::unique_ptr<std::mutex> the_mutex;
int main()
{
// before any theread is created:
the_mutex = new std::mutex();
// ...
return 0;
}
Again, the mutex will be cleaned up automatically, this time via the smart pointer. I assume that you are aware that you shold, though, never ever change the object contained in the smart pointer, otherwise you break your protection against race conditions.
One last point:
[...], I have added a mutex inside the global object.
OK, your mutex is part of the global object. If you want to retain thread safety, the global object now must exist during the whole life time of your program (or at least as long as there are multiple threads running). If you cannot assure this by your program design - then you need to move the mutex out of the class! So either have a separate mutex as above or make the mutex a static member of your class. The latter option again provides automatic cleanup as the former already does.
Edit:
According to your comment, what you want to achieve is protecting smaller parts of a larger tree against race conditions such that the nodes can be used independently, providing smaller lock ranges/durations.
With the approach you are planning, you get into trouble as soon as you try to modify the whole tree: Imagine you are going to delete one node in thread A. A gets the mutex, but is then interrupted. Another thread B tries to lock the mutex, too, to modify the object in question, but fails to do so and has to wait. A now deletes the object, and B operates on invalid data from now on!
So on modification, you need to protect the whole tree! If you are on the newest C++ standard, you can use a global/static std::shared_mutex to secure your tree: Every read access to a node is protected with a shared_lock to the entire tree, each write access (adding or deleting nodes) with a normal lock.
Otherwise, boost offers a similar facility and you find solutions here on stackoverflow (e. g. here or here).
I'm using boost to start a thread and the thread function is a member function of my class just like this:
class MyClass {
public:
void ThreadFunc();
void StartThread() {
worker_thread_ = boost::shared_ptr<boost::thread>(
new boost::thread(boost::bind(&MyClass::ThreadFunc, this)));
}
};
I will access some member variables in ThreadFunc:
while (!stop) {
Sleep(1000); // here will be some block operations
auto it = this->list.begin();
if (it != this->list.end())
...
}
I can not wait forever for thread return, so I set timeout:
stop = true;
worker_thread_->interrupt();
worker_thread_->timed_join(boost::posix_time::milliseconds(timeout_ms));
After timeout, I will delete this MyClass pointer. Here will be a problem, the ThreadFunc hasn't return, it will have chances to access this and its member variables. In my case, the iterator will be invalid and it != this->list.end() will be true, so my program will crash if using invalid iterator.
My question is how to avoid it ? Or how to check whether this is valid or member variables is valid ? Or could I set some flags to tell ThreadFunc the destructor has been called ?
There are a lot of possible solutions. One is to use a shared_ptr to the class and let the thread hold its own shared_ptr to the class. That way, the object will automatically get destroyed only when both threads are done with it.
How about you create a stopProcessing flag (make it atomic) as a member of MyClass and in your ThreadFunc method check at each cycle if this flag is set?
[EDIT: making clearer the answer]
There a two orthogonal problems:
stopping the processing (I lost my patience, stop now please). This can be arranged by setting a flag into MyClass and make ThreadFunc checking it as often as reasonable possible
deallocation of resources. This is best by using RAII - one example being the use of shared_ptr
Better keep them as separate concerns.
Combining them in a single operation may be possible, but risky.
E.g. if using shared_ptr, the once the joining thread decided "I had enough", it simply goes out of the block which keeps its "copy" of shared_ptr, thus the shared_ptr::use_count gets decremented. The thread function may notice this and decide to interpret it as an "caller had enough" and cut short the processing.However, this implies that, in the future releases, nobody else (but the two threads) may acquire a shared_ptr, otherwise the "contract" of 'decremented use_count means abort' is broken.
(a use_count==1 condition may still be usable - interpretation "Only me, the processing thread, seems to be interested in the results; no consumer for them, better abort the work").
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++.
I have a thread pool with some threads (e.g. as many as number of cores) that work on many objects, say thousands of objects. Normally I would give each object a mutex to protect access to its internals, lock it when I'm doing work, then release it. When two threads would try to access the same object, one of the threads has to wait.
Now I want to save some resources and be scalable, as there may be thousands of objects, and still only a hand full of threads. I'm thinking about a class design where the thread has some sort of mutex or lock object, and assigns the lock to the object when the object should be accessed. This would save resources, as I only have as much lock objects as I have threads.
Now comes the programming part, where I want to transfer this design into code, but don't know quite where to start. I'm programming in C++ and want to use Boost classes where possible, but self written classes that handle these special requirements are ok. How would I implement this?
My first idea was to have a boost::mutex object per thread, and each object has a boost::shared_ptr that initially is unset (or NULL). Now when I want to access the object, I lock it by creating a scoped_lock object and assign it to the shared_ptr. When the shared_ptr is already set, I wait on the present lock. This idea sounds like a heap full of race conditions, so I sort of abandoned it. Is there another way to accomplish this design? A completely different way?
Edit:
The above description is a bit abstract, so let me add a specific example. Imagine a virtual world with many objects (think > 100.000). Users moving in the world could move through the world and modify objects (e.g. shoot arrows at monsters). When only using one thread, I'm good with a work queue where modifications to objects are queued. I want a more scalable design, though. If 128 core processors are available, I want to use all 128, so use that number of threads, each with work queues. One solution would be to use spatial separation, e.g. use a lock for an area. This could reduce number of locks used, but I'm more interested if there's a design which saves as much locks as possible.
You could use a mutex pool instead of allocating one mutex per resource or one mutex per thread. As mutexes are requested, first check the object in question. If it already has a mutex tagged to it, block on that mutex. If not, assign a mutex to that object and signal it, taking the mutex out of the pool. Once the mutex is unsignaled, clear the slot and return the mutex to the pool.
Without knowing it, what you were looking for is Software Transactional Memory (STM).
STM systems manage with the needed locks internally to ensure the ACI properties (Atomic,Consistent,Isolated). This is a research activity. You can find a lot of STM libraries; in particular I'm working on Boost.STM (The library is not yet for beta test, and the documentation is not really up to date, but you can play with). There are also some compilers that are introducing TM in (as Intel, IBM, and SUN compilers). You can get the draft specification from here
The idea is to identify the critical regions as follows
transaction {
// transactional block
}
and let the STM system to manage with the needed locks as far as it ensures the ACI properties.
The Boost.STM approach let you write things like
int inc_and_ret(stm::object<int>& i) {
BOOST_STM_TRANSACTION {
return ++i;
} BOOST_STM_END_TRANSACTION
}
You can see the couple BOOST_STM_TRANSACTION/BOOST_STM_END_TRANSACTION as a way to determine a scoped implicit lock.
The cost of this pseudo transparency is of 4 meta-data bytes for each stm::object.
Even if this is far from your initial design I really think is what was behind your goal and initial design.
I doubt there's any clean way to accomplish your design. The problem that assigning the mutex to the object looks like it'll modify the contents of the object -- so you need a mutex to protect the object from several threads trying to assign mutexes to it at once, so to keep your first mutex assignment safe, you'd need another mutex to protect the first one.
Personally, I think what you're trying to cure probably isn't a problem in the first place. Before I spent much time on trying to fix it, I'd do a bit of testing to see what (if anything) you lose by simply including a Mutex in each object and being done with it. I doubt you'll need to go any further than that.
If you need to do more than that I'd think of having a thread-safe pool of objects, and anytime a thread wants to operate on an object, it has to obtain ownership from that pool. The call to obtain ownership would release any object currently owned by the requesting thread (to avoid deadlocks), and then give it ownership of the requested object (blocking if the object is currently owned by another thread). The object pool manager would probably operate in a thread by itself, automatically serializing all access to the pool management, so the pool management code could avoid having to lock access to the variables telling it who currently owns what object and such.
Personally, here's what I would do. You have a number of objects, all probably have a key of some sort, say names. So take the following list of people's names:
Bill Clinton
Bill Cosby
John Doe
Abraham Lincoln
Jon Stewart
So now you would create a number of lists: one per letter of the alphabet, say. Bill and Bill would go in one list, John, Jon Abraham all by themselves.
Each list would be assigned to a specific thread - access would have to go through that thread (you would have to marshall operations to an object onto that thread - a great use of functors). Then you only have two places to lock:
thread() {
loop {
scoped_lock lock(list.mutex);
list.objectAccess();
}
}
list_add() {
scoped_lock lock(list.mutex);
list.add(..);
}
Keep the locks to a minimum, and if you're still doing a lot of locking, you can optimise the number of iterations you perform on the objects in your lists from 1 to 5, to minimize the amount of time spent acquiring locks. If your data set grows or is keyed by number, you can do any amount of segregating data to keep the locking to a minimum.
It sounds to me like you need a work queue. If the lock on the work queue became a bottle neck you could switch it around so that each thread had its own work queue then some sort of scheduler would give the incoming object to the thread with the least amount of work to do. The next level up from that is work stealing where threads that have run out of work look at the work queues of other threads.(See Intel's thread building blocks library.)
If I follow you correctly ....
struct table_entry {
void * pObject; // substitute with your object
sem_t sem; // init to empty
int nPenders; // init to zero
};
struct table_entry * table;
object_lock (void * pObject) {
goto label; // yes it is an evil goto
do {
pEntry->nPenders++;
unlock (mutex);
sem_wait (sem);
label:
lock (mutex);
found = search (table, pObject, &pEntry);
} while (found);
add_object_to_table (table, pObject);
unlock (mutex);
}
object_unlock (void * pObject) {
lock (mutex);
pEntry = remove (table, pObject); // assuming it is in the table
if (nPenders != 0) {
nPenders--;
sem_post (pEntry->sem);
}
unlock (mutex);
}
The above should work, but it does have some potential drawbacks such as ...
A possible bottleneck in the search.
Thread starvation. There is no guarantee that any given thread will get out of the do-while loop in object_lock().
However, depending upon your setup, these potential draw-backs might not matter.
Hope this helps.
We here have an interest in a similar model. A solution we have considered is to have a global (or shared) lock but used in the following manner:
A flag that can be atomically set on the object. If you set the flag you then own the object.
You perform your action then reset the variable and signal (broadcast) a condition variable.
If the acquire failed you wait on the condition variable. When it is broadcast you check its state to see if it is available.
It does appear though that we need to lock the mutex each time we change the value of this variable. So there is a lot of locking and unlocking but you do not need to keep the lock for any long period.
With a "shared" lock you have one lock applying to multiple items. You would use some kind of "hash" function to determine which mutex/condition variable applies to this particular entry.
Answer the following question under the #JohnDibling's post.
did you implement this solution ? I've a similar problem and I would like to know how you solved to release the mutex back to the pool. I mean, how do you know, when you release the mutex, that it can be safely put back in queue if you do not know if another thread is holding it ?
by #LeonardoBernardini
I'm currently trying to solve the same kind of problem. My approach is create your own mutex struct (call it counterMutex) with a counter field and the real resource mutex field. So every time you try to lock the counterMutex, first you increment the counter then lock the underlying mutex. When you're done with it, you decrement the coutner and unlock the mutex, after that check the counter to see if it's zero which means no other thread is trying to acquire the lock . If so put the counterMutex back to the pool. Is there a race condition when manipulating the counter? you may ask. The answer is NO. Remember you have a global mutex to ensure that only one thread can access the coutnerMutex at one time.
I have a std::map that is used by multiple threads to store data. The map is declared like this:
std::map<int, Call> calls;
From each thread, I have to acquire a mutex lock, obtain a pointer or reference to the object belonging to that thread, then release the mutex lock. I can modify the object after that because each object is used only by one thread. As soon as the thread dies, the corresponding pair in the map would also get deleted.
I would like to know the best way to implement this. I was thinking of two ways:
1) I know this one could look outrageously crazy, but still
std::map<int, Call> calls;
...
{
mutex.lock();
Call* callptr = &calls[id];
mutex.unlock();
// use callptr
}
or 2) I think this one looks more sensible
std::map<int, std::auto_ptr<Call> > calls;
...
{
mutex.lock();
std::auto_ptr<Call> callptr = map[id];
mutex.unlock();
// use callptr
mutex.lock();
map[id] = callptr;
mutex.unlock();
}
The threads actually are created in a different dll and I don't have the code for that. This dll that I'm writing now gets imported by that dll and used. So it has to be implemented with std::map only, but could anyone tell me if one of these methods is ok or if there are ways to make it more stable.
Thanks
You should use iterators:
mutex.lock();
std::map<int, Call>::iterator callptr = calls.find(id);
callptr->second.foo();
...
mutex.unlock();
Your first solution with pointers is problematic, because the lifetime of the object in the map is uncertain - it may be moved when the tree is rebalanced when elements are inserted or deleted.
Your second solution won't work at all, because std::auto_ptr does not fulfil the requirements for mapped_type of std::map - mostly because its copy constructor and operator= don't actually copy. You likely won't get a compiler error, but you'll get very weird behavior at run-time.
According to me Thread Local storage is the best option for you.
If you need thread specific data, you can make use of Thread Local Storage and completely eliminate the need for map and mutex locking.
Don't use auto_ptr's in STL containers. DON'T. The implementors are actually required to try and make its use there a compilation error. Standard containers tend to copy things around. That's a very wrong thing with auto_ptr.