views:

628

answers:

2

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.

+5  A: 

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(); ... }
antti.huima
While that is true, locking has a great deal of overhead, and so it might not be a bad idea to create thread unsafe versions of the code, first, and then create a lightweight threadsafe wrapper for it.
Michael Aaron Safyan
@Michael: if your mutex implementation supports recursive locking at all, chances are it will support it efficiently. All that's usually required is that the lock function does "if (mutex.owner == thisthread) { ++lockcount; return; }". If you don't have the lock then you're reading the owner field unsynchronized, but provided the implementation knows that reads and writes of the mutex.owner field are atomic (e.g. word reads on x86), you can't get a false positive. If you do have the lock then you can't get a false negative because nothing can change the owner while you hold it.
Steve Jessop
"you can't get a false positive". I should probably mention that there are some further assumptions there - primarily that each time a thread acquires or releases a mutex, the kernel ensures that the mutex.owner field is changed in a way which is visible to that thread (either change it from the thread, or flush the thread's cache of it, or whatever).
Steve Jessop
@Steve, regardless, is it useful to have an unsynchronized implementation in addition to a threadsafe one, because the initial acquisition and final release of the mutex do impose a great deal of overhead, which would be unnecessary in single-threaded code. Also, one cannot assume that the mutex implementation will not suspend signals or do some other expensive operation during the intermediate locks and releases.
Michael Aaron Safyan
Sure, libraries generally shouldn't have built-in thread-safety unless they actually create threads themselves or explicitly operate on multiple threads specified by their clients. Not for performance, but as a separation of concerns - combining multiple self-synchronising chunks of code can rapidly get quite complicated, with locking order and perhaps a need for atomic operations involving data in both domains. So applications need to be able to take over responsibility. Occasionally it doesn't make sense to offer a non-threadsafe version (an unsafe thread pool?), else it should be the norm.
Steve Jessop
As for "acquisition and release impose a great deal of overhead", depends on the context. In the case of a futex in a single-threaded use (so zero contention), it's pretty fast, probably not worth worrying about unless you're also carefully avoiding a lot of other things. Easy enough to measure - if all else fails just comment out the lock/unlock. But if you're in a code where for example a cache miss would ruin your day, I expect it's a concern.
Steve Jessop
"libraries generally shouldn't have built-in thread-safety" - by which I mean, thread safety w.r.t concurrent operations on the same handle/whatever. Re-entrancy and thread safety w.r.t concurrent calls to the code with different data, are both a good idea.
Steve Jessop
A: 

It would certainly be a problem if a thread blocked trying to acquire (again) a mutex it already owned...

Is there a reason to not permit a mutex to be acquired multiple times by the same thread?

Michael Burr
Simplicity of implementation, I think. Also, here's a reasonable factor against recursive mutexes: http://stackoverflow.com/questions/187761/recursive-lock-mutex-vs-non-recursive-lock-mutex/293646#293646. I suspect Java may have pretty much obliterated the average programmer's familiarity with, or ability to use, non-recursive locks.
Steve Jessop