-3

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?

  • 2
    If the object is global, why would you need to "destroy" it? Why not simply let it be destructed when the program exits? – Some programmer dude Mar 28 '17 at 07:13
  • 2
    I agree: what is the point of having a GLOBAL object, when its lifetime isn't "global" regarding the lifeetime of the application?! – GhostCat Mar 28 '17 at 07:15
  • 3
    And to follow on from @Someprogrammerdude 's comment if you need different instances over the lifetime of the app, then the object ***should NOT be global***. – Disillusioned Mar 28 '17 at 07:16
  • Its my mistake while describing the problem. By global data, I don't mean global variable. I mean any object on heap. – Chandan Srivastava Mar 28 '17 at 10:58
  • @ChandanSrivastava Let that be a lesson in the importance of providing a small amount of sample code that exemplifies your problem. – Disillusioned Mar 29 '17 at 00:58

1 Answers1

3

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

Community
  • 1
  • 1
Aconcagua
  • 24,880
  • 4
  • 34
  • 59
  • I can't make as static because it could be many. You can consider it as node of a tree. Where nodes are being added and deleted dynamically. Ann I want to synchronize access to these nodes individually. – Chandan Srivastava Mar 28 '17 at 11:01
  • I see - edited my answer accordingly. – Aconcagua Mar 28 '17 at 11:39
  • Thanks Aconcagua for the reply. – Chandan Srivastava Mar 28 '17 at 12:44
  • Thanks Aconcagua for the reply. But solution explained will not give me that much concurrency. Deleting the node itself is not my problem. On tree level, I am using another mutex to modify (add/delete) a node.So that node will be removed from the tree first and later will be deleted. What I want to safeguard is that while deleting that node, no one is accessing the node. I think, this can be achieved by storing the mutex externally and mapping it to the node rather that storing it inside the node. What is your view on this? – Chandan Srivastava Mar 28 '17 at 12:54
  • @ChandanSrivastava Your concerns about concurrency in a tree structure are an entirely different question. You made ***zero*** mention of the tree in your original question. I suggest you ask a new question and put more effort into explaining your problem. E.g. Why do you want multi-threaded access on your nodes? Understanding the reasons helps understand the constraints of possible solutions. Locking might not be the right approach. _Remember, bad multi-threading is usually much worse than no multi-threading_. – Disillusioned Mar 29 '17 at 01:05
  • @ChandanSrivastava 1. The concurrency you can expect to get with a shared mutex depends on the ratio of shared to exclusive locks you need (i. e. the more you modify the tree, the less concurrency). 2. So you have a global mutex already - do you only aquire it on modifying the tree then? As the tree modification is not atomic, can you guarantee that you do not break iterations and element selection of another thread accessesing the tree read-only? So you might have to hold the lock anyway even on read-access! (Back at the *shared* mutex???) – Aconcagua Mar 29 '17 at 07:34
  • @ChandanSrivastava 3. Moving the mutex out of the nodes will just move the problem to another location, question then still remains: When to delete the mutex? When can you be sure that no other thread tries to lock it right now? – Aconcagua Mar 29 '17 at 07:35