Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use recursive mutex?

I understand recursive mutex allows mutex to be locked more than once without getting to a deadlock and should be unlocked the same number of times. But in what specific situations do you need to use a recursive mutex? I'm looking for design/code-level situations.

like image 964
jasonline Avatar asked Mar 10 '10 07:03

jasonline


People also ask

Why do we need recursive mutex?

If you want to be able to call public methods from different threads inside other public methods of a class and many of these public methods change the state of the object, you should use a recursive mutex.

What is recursive mutex in OS?

In computer science, the reentrant mutex (recursive mutex, recursive lock) is a particular type of mutual exclusion (mutex) device that may be locked multiple times by the same process/thread, without causing a deadlock.

Why are recursive locks bad?

Another problem with recursive locks is that a method can never be sure whether its lock is unlocked. It may already be locked before the method acquires it, and it may still be locked after the method releases it.

What will happen if a non recursive mutex?

Deadlock! If a thread which had already locked a mutex, tries to lock the mutex again, it will enter into waiting list of that mutex which results in deadlock.


2 Answers

For example when you have function that calls it recursively, and you want to get synchronized access to it:

void foo() {    ... mutex_acquire();    ... foo();    ... mutex_release(); } 

without a recursive mutex you would have to create an "entry point" function first, and this becomes cumbersome when you have a set of functions that are mutually recursive. Without recursive mutex:

void foo_entry() {    mutex_acquire(); foo(); mutex_release(); }  void foo() { ... foo(); ... } 
like image 117
Antti Huima Avatar answered Oct 05 '22 13:10

Antti Huima


Recursive and non-recursive mutexes have different use cases. No mutex type can easily replace the other. Non-recursive mutexes have less overhead, and recursive mutexes have in some situations useful or even needed semantics and in other situations dangerous or even broken semantics. In most cases, someone can replace any strategy using recursive mutexes with a different safer and more efficient strategy based on the usage of non-recursive mutexes.

  • If you just want to exclude other threads from using your mutex protected resource, then you could use any mutex type, but might want to use the non-recursive mutex because of its smaller overhead.
  • If you want to call functions recursively, which lock the same mutex, then they either
    • have to use one recursive mutex, or
    • have to unlock and lock the same non-recursive mutex again and again (beware of concurrent threads!) (assuming this is semantically sound, it could still be a performance issue), or
    • have to somehow annotate which mutexes they already locked (simulating recursive ownership/mutexes).
  • If you want to lock several mutex-protected objects from a set of such objects, where the sets could have been built by merging, you can choose
    • to use per object exactly one mutex, allowing more threads to work in parallel, or
    • to use per object one reference to any possibly shared recursive mutex, to lower the probability of failing to lock all mutexes together, or
    • to use per object one comparable reference to any possibly shared non-recursive mutex, circumventing the intent to lock multiple times.
  • If you want to release a lock in a different thread than it has been locked, then you have to use non-recursive locks (or recursive locks which explicitly allow this instead of throwing exceptions).
  • If you want to use synchronization variables, then you need to be able to explicitly unlock the mutex while waiting on any synchronization variable, so that the resource is allowed to be used in other threads. That is only sanely possible with non-recursive mutexes, because recursive mutexes could already have been locked by the caller of the current function.
like image 26
comonad Avatar answered Oct 05 '22 12:10

comonad