Discussion:
proper order of pthread_mutex_unlock() and pthread_cond_signal()
(too old to reply)
e***@nospam.com
2005-01-31 22:41:44 UTC
Permalink
Hi,

Consider following pseudo-code:

void foo() {
pthread_mutex_lock(&mux);
while (in_use == 0) {
pthread_cond_wait(&cond, &mux);
}
in_use=0;
pthread_mutex_unlock(&mux);
pthread_cond_signal(&cond);
}

I've read that pthread_cond_signal(&cond) should actually be inside the
locked code segment (critical section) and not outside as shown in the
example above. Any comments on why one of the correct solutions is the
way to go? Both work for me but I'm quite confident that one is wrong.

Regards,
Roberto Nibali, ratz
--
echo
'[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq' | dc
Eric Sosman
2005-01-31 23:04:06 UTC
Permalink
Post by e***@nospam.com
Hi,
void foo() {
pthread_mutex_lock(&mux);
while (in_use == 0) {
pthread_cond_wait(&cond, &mux);
}
in_use=0;
pthread_mutex_unlock(&mux);
pthread_cond_signal(&cond);
}
I've read that pthread_cond_signal(&cond) should actually be inside the
locked code segment (critical section) and not outside as shown in the
example above. Any comments on why one of the correct solutions is the
way to go? Both work for me but I'm quite confident that one is wrong.
It is said that signalling with the mutex lock can
lead to "more predictable scheduling behavior." Consider
a scenario where thread A signals while thread B is parked
in cond_wait, but thread C is also interested in the same
mutex. If A unlocks and then signals, C may re-lock the
mutex and perhaps change the predicate before B can awaken.
If A signals and then unlocks this can still happen, but
may be less likely.

However, a program that depends so sensitively on the
vagaries of thread scheduling is suspect to begin with:
why should you care whether B gets its chance before or
after C? Or, if you do care, why aren't you doing something
explicit about it instead of relying on fiddly implementation
details? If the exact ordering of B and C is unimportant
or is being handled in some other way, then it seems to me
that another principle should rule: Keep critical regions
as short as is practical, that is, hold locks for the least
time you can comfortably manage. This principle suggests
that unlocking and then signalling is preferable: cond_signal
doesn't need mutex protection, hence cond_signal can be moved
outside the critical section, hence it *should* be outside.

Neither arrangement is "right" or "wrong," but I think
it is usually better to unlock first and signal afterward.
Of course, if the program requires a particular ordering of
B and C and hasn't taken other steps to enforce it, the program
is already broken beyond the power of a simple rearrangement
to repair it.
--
***@sun.com
e***@nospam.com
2005-01-31 23:47:55 UTC
Permalink
Hello Eric,
Post by Eric Sosman
It is said that signalling with the mutex lock can
lead to "more predictable scheduling behavior." Consider
a scenario where thread A signals while thread B is parked
in cond_wait, but thread C is also interested in the same
mutex. If A unlocks and then signals, C may re-lock the
mutex and perhaps change the predicate before B can awaken.
If A signals and then unlocks this can still happen, but
may be less likely.
Your explanation makes a lot of sense.
Post by Eric Sosman
However, a program that depends so sensitively on the
Fully agreed.
Post by Eric Sosman
why should you care whether B gets its chance before or
after C? Or, if you do care, why aren't you doing something
explicit about it instead of relying on fiddly implementation
details? If the exact ordering of B and C is unimportant
or is being handled in some other way, then it seems to me
that another principle should rule: Keep critical regions
as short as is practical, that is, hold locks for the least
time you can comfortably manage. This principle suggests
that unlocking and then signalling is preferable: cond_signal
doesn't need mutex protection, hence cond_signal can be moved
outside the critical section, hence it *should* be outside.
I think so too.
Post by Eric Sosman
Neither arrangement is "right" or "wrong," but I think
it is usually better to unlock first and signal afterward.
Of course, if the program requires a particular ordering of
B and C and hasn't taken other steps to enforce it, the program
is already broken beyond the power of a simple rearrangement
to repair it.
Thank you very much for your excellent explanation, it all makes perfect
sense. I was confused since I read the example code in the O'Reilly book
"Pthreads Programming" written by Nichols, Buttlar and Farrell and they
signal first and then unlock (p80-81).

Best regards,
Roberto Nibali, ratz
--
echo
'[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq' | dc
David Schwartz
2005-02-01 04:52:13 UTC
Permalink
Post by e***@nospam.com
I've read that pthread_cond_signal(&cond) should actually be inside the
locked code segment (critical section) and not outside as shown in the
example above. Any comments on why one of the correct solutions is the way
to go? Both work for me but I'm quite confident that one is wrong.
Generally, placing the signal outside the critical section results in
better performance. It is possible to, if incredibly clever, create a
situation where this doesn't work (because the pthread_cond_signal, being
later, can wake a thread that went to sleep after the mutex was released,
and thus is waiting on the wrong predicate), but such a situation has never
occured in the wild.

DS
Markus Elfring
2005-02-01 06:19:02 UTC
Permalink
Post by e***@nospam.com
I've read that pthread_cond_signal(&cond) should actually be inside the
locked code segment (critical section) and not outside as shown in the
example above. Any comments on why one of the correct solutions is the
way to go? Both work for me but I'm quite confident that one is wrong.
The discussion "A word of caution when juggling
pthread_cond_signal/pthread_mutex_unlock" contains some useful descriptions
already.
http://groups.google.de/groups?threadm=d976b79f.0403182115.45c8fed4%40posting.go
ogle.com

Regards,
Markus
e***@nospam.com
2005-02-05 21:10:46 UTC
Permalink
Post by Markus Elfring
The discussion "A word of caution when juggling
pthread_cond_signal/pthread_mutex_unlock" contains some useful descriptions
already.
http://groups.google.de/groups?threadm=d976b79f.0403182115.45c8fed4%40posting.go
ogle.com
Excellent. Thanks all of you guys for the replies.

Cheers,
Roberto Nibali, ratz
--
echo
'[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq' | dc
Loading...