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).