Discussion:
recursive mutexes
(too old to reply)
red floyd
2004-07-15 19:09:51 UTC
Permalink
Does POSIX define what happens when a pthread currently holding a mutex
locks the same mutex?

i.e.

void f()
{
pthread_mutex_lock(&some_mutex);
pthread_mutex_lock(&some_mutex);
}

The Linux (MDK9.1) implementation of pthreads has a non-portable mutex
attribute letting you specify what behavior you want in said situation.

I'd like to try to write portable code, though.
j***@invalid.address
2004-07-15 19:15:12 UTC
Permalink
Post by red floyd
Does POSIX define what happens when a pthread currently holding a
mutex locks the same mutex?
Yes, see

http://www.opengroup.org/onlinepubs/009695399/functions/pthread_mutex_lock.html

Joe
--
We can't all be heroes because someone has to sit on the curb and
clap as they go by.
- Will Rogers
Casper H.S. Dik
2004-07-15 19:55:24 UTC
Permalink
Post by red floyd
Does POSIX define what happens when a pthread currently holding a mutex
locks the same mutex?
i.e.
void f()
{
pthread_mutex_lock(&some_mutex);
pthread_mutex_lock(&some_mutex);
}
The Linux (MDK9.1) implementation of pthreads has a non-portable mutex
attribute letting you specify what behavior you want in said situation.
I'd like to try to write portable code, though.
Portable:

pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
red floyd
2004-07-15 20:54:56 UTC
Permalink
Post by Casper H.S. Dik
Post by red floyd
Does POSIX define what happens when a pthread currently holding a mutex
locks the same mutex?
i.e.
void f()
{
pthread_mutex_lock(&some_mutex);
pthread_mutex_lock(&some_mutex);
}
The Linux (MDK9.1) implementation of pthreads has a non-portable mutex
attribute letting you specify what behavior you want in said situation.
I'd like to try to write portable code, though.
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
Casper
OK, thanks Joe and Casper. I guess my systems implementation is older,
and thus the recursive mutex hadn't yet been standardized or something.
So I'll simply #define something like this

#ifdef USE_NON_PORTABLE_RECURSIVE_MUTEX_
#define RECURSIVE_MUTEX_ATTR PTHREAD_MUTEX_RECURSIVE_NP /* MDK9.1 */
#else
#define RECURSIVE_MUTEX_ATTR PTHREAD_MUTEX_RECURSIVE /* other */
#endif

and use RECURSIVE_MUTEX_ATTR, so that I don't have to worry about it in
the future.
Alexander Terekhov
2004-07-15 21:29:27 UTC
Permalink
red floyd wrote: ...

Don't use recursive mutexes. It's akin to sex with used condoms. ;-)

regards,
alexander.
Loic Domaigne
2004-07-15 23:42:20 UTC
Permalink
Hello,
Post by Alexander Terekhov
Don't use recursive mutexes. It's akin to sex with used condoms. ;-)
what's going on, Alexander? Are you now using now sentences that everybody can
understand?

I am not used to that ;-)

Cheers,
Loic.
--
Article posté via l'accès Usenet http://www.mes-news.com
Accès par Nnrp ou Web
SenderX
2004-07-15 23:45:07 UTC
Permalink
Post by Alexander Terekhov
Don't use recursive mutexes. It's akin to sex with used condoms. ;-)
YIKES!
red floyd
2004-07-15 23:45:08 UTC
Permalink
Post by Alexander Terekhov
red floyd wrote: ...
Don't use recursive mutexes. It's akin to sex with used condoms. ;-)
regards,
alexander.
May I ask why?
David Schwartz
2004-07-15 23:59:58 UTC
Permalink
Post by red floyd
May I ask why?
There are two possibilities:

1) You don't know the mutex is being used recursively. In this case, the
recursive mutex will hide a serious problem.

2) You know the mutex is being recursively. In this case, just don't
lock it since you know it's already locked anyway.

The problem is that recursive mutexes hide something from you and that
something is extremely important. Consider code like this:

A) Lock mutex
B) Unlock mutex
C) Do something, assuming the mutex is unlocked

What happens if the mutex is recursive?

The only value of a recursive mutex is that it allows you to write a
function that works properly whether or not a mutex is locked. But the
caller must know that the mutex is locked anyway, so why not just have two
versions of the function? (With the one you call without a lock possibly
just being a wrapper that grabs the lock and calls the other function.)

It's just too hard and dangerous to write sensible code that works with
a mutex that might or might not start out with that mutex locked and with no
way to tell which. And the only value of recursive mutexes is that they let
you do this.

DS
SenderX
2004-07-16 00:21:05 UTC
Permalink
Post by David Schwartz
It's just too hard and dangerous to write sensible code that works with
a mutex that might or might not start out with that mutex locked and with no
way to tell which. And the only value of recursive mutexes is that they let
you do this.
There good for hashed locks.
David Schwartz
2004-07-16 02:47:24 UTC
Permalink
Post by SenderX
Post by David Schwartz
It's just too hard and dangerous to write sensible code that
works with a mutex that might or might not start out with that mutex
locked and with no way to tell which. And the only value of
recursive mutexes is that they let you do this.
There good for hashed locks.
I can't imagine how. The only way they might help is if you have code
that grabs more than one object and they might 'happen to' have the same
lock protecting them. But if your code does this, they might also happen to
have different locks protecting them. In this case, you must enforce your
lock ordering rules or else you can deadlock.

In other words, if one thread can grab object A then object B, grabbing
lock 1 followed by lock 2, another thread could grab object C followed by
object D, grabbing lock 2 followed by lock 1. Then you deadlock.

So if you're going to use hashed locks, you may either hold two locks at
once or you may not. If you may not, recursive locks don't help.

If you may, then you must check to see what locks they refer to so that
you acquire them in the right order. While you're doing this, it's just as
easy to check if they're the same lock, and if so only acquire it once. So
recursive locks don't help you in this case.

Worse, recursive locks might lull you into thinking you don't have to
check what locks you are acquiring, and then you are vulnerable to lock
order reversal and deadlocks.

DS
Martin James
2004-07-16 14:59:25 UTC
Permalink
Post by David Schwartz
It's just too hard and dangerous to write sensible code that works with
a mutex that might or might not start out with that mutex locked and with no
way to tell which. And the only value of recursive mutexes is that they let
you do this.
Uhh.. OK I have a class protected by an internal mutex. I wish to derive
from the class & add some extra private data & methods in my descendant. I
want the private data in the child to be protected by the mutex, so I obtain
it in the child. The methods in the child call the inherited methods of the
parent, which attempt to get the mutex.again & deadlock the single caller.

Now what? I can add protected 'unlocked' methods in the parent class that
are called from public methods in the parent that get the mutex first. The
child must then ensure that it only calls the unlocked methods that don't
get the mutex. Is this messy & dangerous compared with recursive mutexes or
what?

No, I will not use two mutexes :)

Rgds,
Martin
David Schwartz
2004-07-16 18:14:46 UTC
Permalink
Post by Martin James
Post by David Schwartz
It's just too hard and dangerous to write sensible code that
works with a mutex that might or might not start out with that mutex
locked and with no way to tell which. And the only value of
recursive mutexes is that they let you do this.
Uhh.. OK I have a class protected by an internal mutex. I wish to
derive from the class & add some extra private data & methods in my
descendant. I want the private data in the child to be protected by
the mutex, so I obtain it in the child. The methods in the child
call the inherited methods of the parent, which attempt to get the
mutex.again & deadlock the single caller.
Right, that would be bad.
Post by Martin James
Now what? I can add protected 'unlocked' methods in the parent
class that are called from public methods in the parent that get the
mutex first. The child must then ensure that it only calls the
unlocked methods that don't get the mutex. Is this messy & dangerous
compared with recursive mutexes or what?
No, it's cleaner and safer by *far*. What happens when someone adds some
code to the class that looks like this:

LockMutex();
while (ObjectIsNotReady())
{
UnlockMutex();
BlockOnEvent();
LockMutex();
}
DoStuff();
UnlockMutex();

Now, all of a sudden, that 'UnlockMutex()' is a nop, and the loop will
spin forever. The problem is that the functions in the inner class can
*only* look exactly like this:

LockMutex();
DoStuff();
UnlockMutex();

Otherwise, the functionality in derived classes may change what code is
run holding the mutex and what code is run without it, and that's very, very
scary.
Post by Martin James
No, I will not use two mutexes :)
That may or may not make more sense.

DS
Martin James
2004-07-16 19:00:14 UTC
Permalink
Post by David Schwartz
No, it's cleaner and safer by *far*. What happens when someone adds some
LockMutex();
while (ObjectIsNotReady())
{
UnlockMutex();
BlockOnEvent();
LockMutex();
}
DoStuff();
UnlockMutex();
Now, all of a sudden, that 'UnlockMutex()' is a nop, and the loop will
spin forever.
I guess it's a moot point whether a deadlock or livelock is spotted first :)

The problem is that the functions in the inner class can
Post by David Schwartz
LockMutex();
DoStuff();
UnlockMutex();
Anther moot point is whether the chances of a developer adding dubious code
that attmpts to unlock a mutex inside an encapsulated object is any greater
or less than a developer accidentally calling the locking, rather than the
lockfree, method of a parent.
Post by David Schwartz
Otherwise, the functionality in derived classes may change what code is
run holding the mutex and what code is run without it, and that's very, very
scary.
Once acquired, always acquired, that's what I say :)

I have to agree that code can be written to screw up almost anything. I'm
Post by David Schwartz
LockMutex();
DoStuff();
UnlockMutex();
in order to avoid the complications of locking and unlocking methods in the
same class.
Post by David Schwartz
Post by Martin James
No, I will not use two mutexes :)
That may or may not make more sense.
No thanks. Four classes down, I'm acquiring four mutexes & some developer
will find a way of acquiring them out-of-order.

Rgds,
Martin
David Schwartz
2004-07-16 20:59:12 UTC
Permalink
Post by Martin James
No thanks. Four classes down, I'm acquiring four mutexes & some
developer will find a way of acquiring them out-of-order.
Recursive mutexes make the risk of this *much* greater and *much* harder
to detect. What happens when some member of your class hierarchy calls
another function that needs to acquire a mutex?

DS
Uenal Mutlu
2005-05-15 06:05:49 UTC
Permalink
Post by David Schwartz
Post by red floyd
May I ask why?
1) You don't know the mutex is being used recursively. In this case, the
recursive mutex will hide a serious problem.
2) You know the mutex is being recursively. In this case, just don't
lock it since you know it's already locked anyway.
The problem is that recursive mutexes hide something from you and that
A) Lock mutex
B) Unlock mutex
C) Do something, assuming the mutex is unlocked
What happens if the mutex is recursive?
Recursive locks work only for the same (current) thread.
The code above is IMO wrong, obviously it should be:
A) Lock mutex
B) Do something
C) Unlock mutex

and this is ok too (here the recursive feature is in action):
A) Lock mutex
B) Do something
C) Lock mutex
D) Do something2
E) Unlock mutex
F) Unlock mutex

C and E are redundant, however application code (the current thread)
cannot always know that it alread has the lock, though it could test for it.
But testing is unnessary because calling such a Lock() will already do
the testing implicitly, so then there is no need for an explicit testing in
applic code, it just would make code longer and slow down the performance.

To clarify:
there is Lock() without recursive feature,
and there is Lock() with recursive feature.
And: such lock objects are initialized at creation.
Post by David Schwartz
The only value of a recursive mutex is that it allows you to write a
function that works properly whether or not a mutex is locked. But the
caller must know that the mutex is locked anyway, so why not just have two
usually the calling thread must not know that; it simply can issue a Lock()
request of its own. If it is already locked by this thread then recursion
is in effect and the lock will be granted very fast.
Post by David Schwartz
versions of the function? (With the one you call without a lock possibly
just being a wrapper that grabs the lock and calls the other function.)
It's just too hard and dangerous to write sensible code that works with
a mutex that might or might not start out with that mutex locked and with no
way to tell which. And the only value of recursive mutexes is that they let
you do this.
Lock objects are initialized at creation, they don't have a random state.
Recursive locks are very practical. It saves coding and prevents from self-deadlocking.
David Schwartz
2005-05-15 10:13:43 UTC
Permalink
Post by Uenal Mutlu
C and E are redundant, however application code (the current thread)
cannot always know that it alread has the lock, though it could test for it.
Yes, it can and must know that it already has the lock. A function that
operates on X should be defined as being called with X locked, or with X
unlocked. It could even take a boolean that indicates whether the caller has
locked the object or not, though this is rarely the right thing to do.

Simply put, the only thing recursive mutexes gives you is the ability to
write code that deals with X that can be called whether or not X is locked.
This is not only almost never useful, but it's almost always dangerous.

DS
Uenal Mutlu
2005-05-15 12:41:38 UTC
Permalink
Post by David Schwartz
Post by Uenal Mutlu
C and E are redundant, however application code (the current thread)
cannot always know that it alread has the lock, though it could test for it.
Yes, it can and must know that it already has the lock. A function that
operates on X should be defined as being called with X locked, or with X
unlocked. It could even take a boolean that indicates whether the caller has
locked the object or not, though this is rarely the right thing to do.
You are unnecessarily complicating things and make the program
slower by doing these testings. These tests are not necessary if
your design is good.
Post by David Schwartz
Simply put, the only thing recursive mutexes gives you is the ability to
write code that deals with X that can be called whether or not X is locked.
Not true. It is the caller's job to call X only after having the lock.
It is not X's job to check whether the object was locked.
Do you see the difference, and the consequence, and what it means for performance?
Post by David Schwartz
This is not only almost never useful, but it's almost always dangerous.
Recursive locking has less dangers than locking without recursive feature.
Proof: using recursive locking you never can block or deadlock yourself,
but using a locking method without recursive feature you can very easily deadlock yourself.
In the latter case even just blocking (ie. waiting for the lock) means deadlock!
Don't you see that?
David Schwartz
2005-05-15 18:56:08 UTC
Permalink
Post by Uenal Mutlu
Recursive locking has less dangers than locking without recursive feature.
Proof: using recursive locking you never can block or deadlock yourself,
but using a locking method without recursive feature you can very easily
deadlock
yourself.
In the latter case even just blocking (ie. waiting for the lock) means deadlock!
Don't you see that?
Okay, suppose I write a function that supposed to only be called if X is
not locked. Calling it with X locked is a *bug*. Now suppose I make a
mistake -- I am only human. I call the function by mistake with X locked.
The function goes to lock X itself. I *want* this to break because it
indicates a *bug*. It is *bad* if this just magically works because then the
bug will not get discovered.

DS
Måns Rullgård
2005-05-15 19:01:10 UTC
Permalink
Post by David Schwartz
Post by Uenal Mutlu
Recursive locking has less dangers than locking without recursive feature.
Proof: using recursive locking you never can block or deadlock yourself,
but using a locking method without recursive feature you can very easily
deadlock
yourself.
In the latter case even just blocking (ie. waiting for the lock) means deadlock!
Don't you see that?
Okay, suppose I write a function that supposed to only be called if X is
not locked. Calling it with X locked is a *bug*. Now suppose I make a
mistake -- I am only human. I call the function by mistake with X locked.
The function goes to lock X itself. I *want* this to break because it
indicates a *bug*. It is *bad* if this just magically works because then the
bug will not get discovered.
In other words, recursive mutexes are nothing but a way of papering
over design flaws in an application.
--
Måns Rullgård
***@inprovide.com
Torsten Robitzki
2005-05-16 12:50:36 UTC
Permalink
Post by Uenal Mutlu
Post by David Schwartz
Yes, it can and must know that it already has the lock. A function that
operates on X should be defined as being called with X locked, or with X
unlocked. It could even take a boolean that indicates whether the caller has
locked the object or not, though this is rarely the right thing to do.
You are unnecessarily complicating things and make the program
slower by doing these testings.
It doesn't really matter if you code this test by yourself or let the
recursive lock do this test for you. As this explicit coded flag does
not need any synchronization it might even be faster then the necessary
test a recursive lock have to do.
Post by Uenal Mutlu
These tests are not necessary if
your design is good.
Right, and the only way to get rid of this tests is to design the code
in such a way that you know for every function if a lock is held of if a
lock have to be acquired.

regards
Torsten

P.S. never used recursive locks and never had any serious problems with
deadlocks.
Måns Rullgård
2005-05-15 10:41:35 UTC
Permalink
Post by Uenal Mutlu
Post by David Schwartz
Post by red floyd
May I ask why?
1) You don't know the mutex is being used recursively. In this case, the
recursive mutex will hide a serious problem.
2) You know the mutex is being recursively. In this case, just don't
lock it since you know it's already locked anyway.
The problem is that recursive mutexes hide something from you and that
A) Lock mutex
B) Unlock mutex
C) Do something, assuming the mutex is unlocked
What happens if the mutex is recursive?
Recursive locks work only for the same (current) thread.
I sure hope so.
Post by Uenal Mutlu
A) Lock mutex
B) Do something
C) Unlock mutex
David meant what he said. What if the something is signaling another
thread to go ahead with something that locks the mutex, and then wait
for that other thread to signal you back? Deadlock.
Post by Uenal Mutlu
A) Lock mutex
B) Do something
C) Lock mutex
D) Do something2
E) Unlock mutex
F) Unlock mutex
C and E are redundant, however application code (the current thread)
cannot always know that it alread has the lock, though it could test for it.
Bad application design. A properly designed application will always
know what to expect.
Post by Uenal Mutlu
Post by David Schwartz
It's just too hard and dangerous to write sensible code that
works with a mutex that might or might not start out with that
mutex locked and with no way to tell which. And the only value of
recursive mutexes is that they let you do this.
Lock objects are initialized at creation, they don't have a random
state. Recursive locks are very practical. It saves coding and
prevents from self-deadlocking.
In all the years I've been programming, I have never used a recursive
mutex (except in Java, but that's another story).
--
Måns Rullgård
***@inprovide.com
Uenal Mutlu
2005-05-15 13:01:02 UTC
Permalink
Post by Måns Rullgård
Post by Uenal Mutlu
Post by David Schwartz
Post by red floyd
May I ask why?
1) You don't know the mutex is being used recursively. In this case, the
recursive mutex will hide a serious problem.
2) You know the mutex is being recursively. In this case, just don't
lock it since you know it's already locked anyway.
The problem is that recursive mutexes hide something from you and that
A) Lock mutex
B) Unlock mutex
C) Do something, assuming the mutex is unlocked
What happens if the mutex is recursive?
Recursive locks work only for the same (current) thread.
I sure hope so.
Post by Uenal Mutlu
A) Lock mutex
B) Do something
C) Unlock mutex
David meant what he said. What if the something is signaling another
thread to go ahead with something that locks the mutex, and then wait
for that other thread to signal you back? Deadlock.
This has nothing to do with recursive locking per se, does it? I mean: the same
would happen also without recursive locking, wouldn't it?
And, apart from that I don't think this way. In my thinking each thread
knows itself only and tries to lock the shared object(s) before changing
its/their content. We are talking of locking some shared objects here, don't we?
You maybe should give a practical example in pseudocode for what you mean.
Post by Måns Rullgård
Post by Uenal Mutlu
A) Lock mutex
B) Do something
C) Lock mutex
D) Do something2
E) Unlock mutex
F) Unlock mutex
C and E are redundant, however application code (the current thread)
cannot always know that it alread has the lock, though it could test for it.
Bad application design. A properly designed application will always
know what to expect.
This is a shortsighted view. What do you think recursive locking is intended for?
Recursive locking has nearly no overhead if the implementation of lock()
and unlock() were properly done.
They have many many advantages.
Post by Måns Rullgård
Post by Uenal Mutlu
Post by David Schwartz
It's just too hard and dangerous to write sensible code that
works with a mutex that might or might not start out with that
mutex locked and with no way to tell which. And the only value of
recursive mutexes is that they let you do this.
Lock objects are initialized at creation, they don't have a random
state. Recursive locks are very practical. It saves coding and
prevents from self-deadlocking.
In all the years I've been programming, I have never used a recursive
mutex (except in Java, but that's another story).
Then you must have overlooked their real value.
Måns Rullgård
2005-05-15 13:18:36 UTC
Permalink
Post by Uenal Mutlu
Post by Måns Rullgård
Post by Uenal Mutlu
Post by David Schwartz
The problem is that recursive mutexes hide something from
you and that something is extremely important. Consider code
A) Lock mutex
B) Unlock mutex
C) Do something, assuming the mutex is unlocked
What happens if the mutex is recursive?
Recursive locks work only for the same (current) thread.
I sure hope so.
Post by Uenal Mutlu
A) Lock mutex
B) Do something
C) Unlock mutex
David meant what he said. What if the something is signaling another
thread to go ahead with something that locks the mutex, and then wait
for that other thread to signal you back? Deadlock.
This has nothing to do with recursive locking per se, does it? I
mean: the same would happen also without recursive locking, wouldn't
it?
No, because having unlocked the mutex, you can be certain that the
other thread will be able to acquire it. If the mutex is recursive,
you can't know which level you just unlocked.
Post by Uenal Mutlu
And, apart from that I don't think this way. In my thinking each
thread knows itself only and tries to lock the shared object(s)
before changing its/their content. We are talking of locking some
shared objects here, don't we?
If "each thread knows itself only", how can we be talking about shared
objects at all?
Post by Uenal Mutlu
You maybe should give a practical example in pseudocode for what you mean.
I don't think that's needed.
Post by Uenal Mutlu
Post by Måns Rullgård
Post by Uenal Mutlu
A) Lock mutex
B) Do something
C) Lock mutex
D) Do something2
E) Unlock mutex
F) Unlock mutex
C and E are redundant, however application code (the current thread)
cannot always know that it alread has the lock, though it could test for it.
Bad application design. A properly designed application will always
know what to expect.
This is a shortsighted view. What do you think recursive locking is intended for?
They are for lazy programmers unwilling to learn proper design.
Post by Uenal Mutlu
Recursive locking has nearly no overhead if the implementation of lock()
and unlock() were properly done.
I'm not worried about overhead. I'm worried about writing buggy code.
Post by Uenal Mutlu
They have many many advantages.
Prove it. Show me one problem that can't be solved better without them.
Post by Uenal Mutlu
Post by Måns Rullgård
Post by Uenal Mutlu
Post by David Schwartz
It's just too hard and dangerous to write sensible code that
works with a mutex that might or might not start out with that
mutex locked and with no way to tell which. And the only value of
recursive mutexes is that they let you do this.
Lock objects are initialized at creation, they don't have a random
state. Recursive locks are very practical. It saves coding and
prevents from self-deadlocking.
In all the years I've been programming, I have never used a recursive
mutex (except in Java, but that's another story).
Then you must have overlooked their real value.
Or I realized their real danger.
--
Måns Rullgård
***@inprovide.com
Uenal Mutlu
2005-05-15 14:45:03 UTC
Permalink
Post by Måns Rullgård
Post by Uenal Mutlu
Post by Måns Rullgård
Post by Uenal Mutlu
Post by David Schwartz
The problem is that recursive mutexes hide something from
you and that something is extremely important. Consider code
A) Lock mutex
B) Unlock mutex
C) Do something, assuming the mutex is unlocked
What happens if the mutex is recursive?
Recursive locks work only for the same (current) thread.
I sure hope so.
Post by Uenal Mutlu
A) Lock mutex
B) Do something
C) Unlock mutex
David meant what he said. What if the something is signaling another
thread to go ahead with something that locks the mutex, and then wait
for that other thread to signal you back? Deadlock.
This has nothing to do with recursive locking per se, does it? I
mean: the same would happen also without recursive locking, wouldn't
it?
No, because having unlocked the mutex, you can be certain that the
other thread will be able to acquire it. If the mutex is recursive,
you can't know which level you just unlocked.
You are expecting a specific thread will get the released lock?
This can't work.
Post by Måns Rullgård
Post by Uenal Mutlu
And, apart from that I don't think this way. In my thinking each
thread knows itself only and tries to lock the shared object(s)
before changing its/their content. We are talking of locking some
shared objects here, don't we?
If "each thread knows itself only", how can we be talking about shared
objects at all?
Because we are talking of threads and not processes...
Post by Måns Rullgård
Post by Uenal Mutlu
You maybe should give a practical example in pseudocode for what you mean.
I don't think that's needed.
It sure would clarify what you mean.
Post by Måns Rullgård
Post by Uenal Mutlu
Post by Måns Rullgård
Post by Uenal Mutlu
A) Lock mutex
B) Do something
C) Lock mutex
D) Do something2
E) Unlock mutex
F) Unlock mutex
C and E are redundant, however application code (the current thread)
cannot always know that it alread has the lock, though it could test for it.
Bad application design. A properly designed application will always
know what to expect.
This is a shortsighted view. What do you think recursive locking is intended for?
They are for lazy programmers unwilling to learn proper design.
I would say this applies exactly to yourself.
Post by Måns Rullgård
Post by Uenal Mutlu
Recursive locking has nearly no overhead if the implementation of lock()
and unlock() were properly done.
I'm not worried about overhead. I'm worried about writing buggy code.
Then continue worrying. Using recursive locking is safer than using
one which doesn't have such recursive feature.
Post by Måns Rullgård
Post by Uenal Mutlu
They have many many advantages.
Prove it. Show me one problem that can't be solved better without them.
Since you don't believe me it's your turn to prove that recursive locking
is more dangerous (your saying) than using no recursive locking.
My point is: recursive locking is much safer than non-recursive locking.
Post by Måns Rullgård
Post by Uenal Mutlu
Post by Måns Rullgård
Post by Uenal Mutlu
Post by David Schwartz
It's just too hard and dangerous to write sensible code that
works with a mutex that might or might not start out with that
mutex locked and with no way to tell which. And the only value of
recursive mutexes is that they let you do this.
Lock objects are initialized at creation, they don't have a random
state. Recursive locks are very practical. It saves coding and
prevents from self-deadlocking.
In all the years I've been programming, I have never used a recursive
mutex (except in Java, but that's another story).
Then you must have overlooked their real value.
Or I realized their real danger.
I doubt it because there is no danger in using recursive locking over
non-recursive locking. OTOH recursive locking has advantages over
non-recursive locking. So what? If you doubt this then prove it.

(Follow-up set to comp.programming.threads where it belongs to)
David Hopwood
2005-05-19 00:31:37 UTC
Permalink
Post by David Schwartz
Post by red floyd
May I ask why?
1) You don't know the mutex is being used recursively. In this case, the
recursive mutex will hide a serious problem.
2) You know the mutex is being recursively. In this case, just don't
lock it since you know it's already locked anyway.
It is sometimes the case that you have code which can usefully be called either
with the mutex already held or with it not already held. This happens in
particular when you have an object protected by a mutex, and some method of
that object can potentially take the same object as an argument.

It's not a very common case, admittedly.
--
David Hopwood <***@blueyonder.co.uk>
Giancarlo Niccolai
2004-07-16 09:32:32 UTC
Permalink
Post by red floyd
Post by Alexander Terekhov
red floyd wrote: ...
Don't use recursive mutexes. It's akin to sex with used condoms. ;-)
regards,
alexander.
May I ask why?
Other than Mr. Schwartz reply (which I consider absolutely good), I may add
also that recursive mutexes are slower (they must check if they are locked
or not) and brings you to program less carefully about shared resource
usage. If you stop to think twice about that, you'll realize that when you
want to lock a resource, you just want to know that you are the owner of
that, and not that you've been entitled to be the owner N times...

The only reason I can see for recursive mutexes is to call recursive
functions, where the locks are so complex that writing a wrapper is not a
viable way, or to create "onion peel" like libraries where the lower levels
are completely obscure and abstracted to the higher ones, and there is
sometimes the need to "extend" the mutex locking also to some function in
the higher levels; but in both the cases there are probably better ways to
deal with the problem with a non recursive mutex, with a little more
cleaner design effort.

Giancarlo.
David Schwartz
2004-07-15 23:59:58 UTC
Permalink
Post by red floyd
May I ask why?
There are two possibilities:

1) You don't know the mutex is being used recursively. In this case, the
recursive mutex will hide a serious problem.

2) You know the mutex is being recursively. In this case, just don't
lock it since you know it's already locked anyway.

The problem is that recursive mutexes hide something from you and that
something is extremely important. Consider code like this:

A) Lock mutex
B) Unlock mutex
C) Do something, assuming the mutex is unlocked

What happens if the mutex is recursive?

The only value of a recursive mutex is that it allows you to write a
function that works properly whether or not a mutex is locked. But the
caller must know that the mutex is locked anyway, so why not just have two
versions of the function? (With the one you call without a lock possibly
just being a wrapper that grabs the lock and calls the other function.)

It's just too hard and dangerous to write sensible code that works with
a mutex that might or might not start out with that mutex locked and with no
way to tell which. And the only value of recursive mutexes is that they let
you do this.

DS
Continue reading on narkive:
Loading...