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).
Related
I have a problem where my code tries to call pthread_mutex_destory() twice. I need to check whether the lock have been destroyed before or not.
How can I do this? Will this work:
void deinit()
{
if(1 == pthread_mutex_trylock(&this->m_lock))
{
(void) pthread_mutex_destroy(&this->m_lock);
}
}
Will trylock only check weather the mutex is locked or not or will it also show me weather it is deleted or not?
Once you destroy a a c object, the data left behind is garbage. c++ doesn't let you do this. (It does but you have to explicitly ask for it.) But you are using a c library, so you have to do everything yourself.
So you have a few options:
use std::mutex which works nicely with c++. But as such, you mutex will have the same lifetime as your containing class. (which is neates)
only use pthread_mutex_destroy in your destructor. Same result as above. You mutex is destroyed as you object is destroyed, which happens exactly once.
use an std::optional to shield the mutex data if it is not initialized.
Wouldn't recommend, as it is an ugly mix of c and c++.
use a bool to keep track whether you mutex is inited.
This is also tricky and ugly as it is prone to mistakes.
I cannot be more specific because i don't know the rest of the code.
I need to check whether the lock have been destroyed before or not.
How can I do this?
You can't affirmatively do it. That is, there is no way to examine a pthread_mutex_t object to determine whether it is initialized. pthread_mutex_init() is not useful for the purpose, and mutex functions other than pthread_mutex_init() have defined behavior only if the mutex is initialized.
You could maintain a separate atomic flag that indicates whether the mutex is initialized, but it is usually best to structure the program so that it is not possible for multiple threads to try to destroy the same mutex. One way that is sometimes viable is simply to avoid destroying them explicitly at all.
Will trylock only check weather the mutex is locked or not or will it also show me weather it is deleted or not?
The behavior of pthread_mutex_trylock() is undefined when the provided pointer does not point to a valid, initialized mutex object. Therefore no, you cannot rely on it to detect whether a mutex has been destroyed.
More generally, there is no safe way to destroy a mutex that may still be contended. Before you destroy a mutex, you need to ensure by some means -- typically the structure of the program -- that there is no possibility of any thread trying to access the mutex during or after its destruction. You cannot rely on the mutex itself for that.
Let's say we've got a global variable, and a global non-member function.
int GlobalVariable = 0;
void GlobalFunction();
and we have
std::mutex MutexObject;
then inside one of the threads, we have this block of code:
{
std::lock_guard<std::mutex> lock(MutexObject);
GlobalVairable++;
GlobalFunction()
}
now, inside another thread running in parallel, what happens if we do thing like this:
{
//std::lock_guard<std::mutex> lock(MutexObject);
GlobalVairable++;
GlobalFunction()
}
So the question is, does a mutex lock only itself from getting owned while being owned by another thread, not caring in the process about what is being tried to be accessed in the critical code? or does the compiler, or in run-time, the OS actually designate the memory location being accessed in the critical code as blocked for now by MutexObject?
My guess is the former, but I need to hear from an experienced programmer; Thanks for taking the time to read my question.
It’s the former. There’s no relationship between the mutex and the objects you’re protecting with the mutex. (In general, it's not possible for the compiler to deduce exactly which objects a given block of code will modify.) The magic behind the mutex comes entirely from the temporal ordering guarantees it makes: that everything the thread does before releasing the mutex is visible to the next thread after it’s grabbed the mutex. But the two threads both need to actively use the mutex for that to happen.
A system which actually cares about what memory locations a thread has accessed and modified, and builds safely on top of that, is “transactional memory”. It’s not widely used.
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 7 years ago.
Improve this question
I cannot post the source code, but I can explain parts of it on a conceptual level and hope I can be helped to understand why my solution works.
I have an application that has 3 threads: A, B and C (main thread).
Thread B has a list of Foo objects.
Each Foo object contains exactly 1 Mutex object, which is a wrapper over recursive mutexes, and a bunch of methods used to set and get various attributes in a synchronizing manner, using the Mutex and 2 of the methods are used to set and get markedForDelete attribute.
All that Thread B does is iterate over said list using iterators, and delete Foo objects marked for delete, or execute other instructions otherwise. It is the only thread in charge with destruction of Foo objects using basic code similar to this:
while (running)
{
fooListLock->Lock();
for (vector<Foo*>::iterator it = fooList.begin(); it)
{
if (it->isMarkedForDelete())
{
it = fooList.erase(it);
}
else
{
it->execute();
}
}
fooListLock->Unlock();
sleep (sleepVariable);
}
Thread A and C will create and add Foo objects to list and they can also mark them to be deleted and it is done in a synchronized manner using other mutexes.
Thread C will occasionally be closed and always afterwards be restarted, but in a controlled manner and never during memory allocation / deallocation and will always release locked mutexes.
The problem is that when Foo's Mutex is allocated in heap memory (via the new operator) the application will reach a deadlock state where Thread C wants to access resources locked by Thread A and the former wants to access a resource locked by Thread B and Thread B is blocked by Foo's Mutex, which is locked, but has no owner. Using GDB I found that the Mutex's pthread_mutex_t owner value is 0 or a negative number, not corresponding to the id of any threads. The blocking end of the deadlock occurs at this piece of code in Thread B: if (it->isMarkedForDelete()).
My very intuitive solution is to allocate Foo's Mutex on the stack and it works without any other modifications ! The application does not ever reach a deadlock state this way.
The compilation is done using g++ 4.8 with the O2 flag set.
I know it's not much to go on, but can someone help me understand why my solution works ?
I certainly believe, it has nothing to do with heap bugs. Most likely, you are not initializing your mutex properly. Are you calling pthread_mutex_initialize?
Let's assume I have a simple class A with one field in C++. This field is initialized in the constructor. Class A also has a method called doit() for modifing the value of this field. doit() will be called from multiple threads. If I have a mutex only in the doit() method, is this sufficient? Do I have a guarantee that I will never read an uninitialized field (because there is no lock in the constructor)?
Edit: I probably was not clear enough. Is there no issue involving processor cache or something similar? I mean, if there is no mutex for initializing memory region (i.e. my field) - is there no risk that the other thread will read some garbage value?
Your object can only be initialised once, and you won't be able use it before it's initialised, so you don't need a mutex there. You will however need a mutex or other suitable lock in your DoIt function, as you said this will be accessed across multiple threads.
Update for edited question: No, you don't need to worry about processor cache. You must construct your object first, before you can have a handle to it. Only once you have this handle can you pass it to other threads to be used. What I'm trying to say is, the spawned threads must start after the construction of the original object, it is impossible for it to happen the other way around!
It is not possible to call doit() on an object that is not created yet, so you do not need mutex in the constructor.
If doit() is the only method that accesses the field, then you should be fine.
If other methods of your class also access that field, even from a single thread, then you must use a mutex also in these methods.
You first need to construct the object before those pesky threads get their hands on it. The OS will allocate memory for the constructor that is only called by one thread. Ths OS looks after that allocation and therefore nothing needs to be done on your part. Hell you can even create two objects of the same class in two different threads.
You can be very conservative and use a mutex at the start of any method that used that field to lock it, and release it and the end.
Or if you understand the interactions of the various methods with the various algorithms , you can use a mutex for critical sections of code that use that field - i.e. That part of the code needs to be sure that the field is not altered by another thread during processing, but you method can release the lock after the critical section, do something else then perhaps have another critical section.
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.