Subj : Re: Futexes are wrong! (Are they?) To : comp.programming.threads From : David Butenhof Date : Tue Jun 07 2005 02:21 pm Maciej Sobczak wrote: > David Schwartz wrote: > >> Generally, you get better performance if you signal after the >> mutex is freed. > > Is there a short way to explain the reason for this difference? > What about wait morph that can be performed for threads waiting on the > condvar while the mutex is still locked by the signalling thread? First, you can't KNOW that the implementation provides wait morphing unless you read the source code; and even that is subject to change for any number of reasons. The scheduling costs of the "early wake" can be substantial. >> This should be used except in the very rare cases where it creates a >> problem. FWIW, in my many years of multi-threaded programming, I have >> never encountered such a case and have only come close to deliberately >> constructing one. > > I'm aware of a compelling design-wise explanation why signalling before > releasing the mutex is good - this is because you signal something that > you know is true at the time of signalling. I agree that doing otherwise > (signalling after freeing the mutex) should not pose any problems in > popular usage patterns, but the "purity" argument sounds good to me. You may be signalling while YOU know the predicate is satisfied; but remember that's no guarantee that the waiter you wake will find it still true when it wakes up. You have to unlock, and you can't be sure the awakened thread will get "first dibs" on the data. "Purity" is a matter of perspective, not reality... especially when talking about only one end of a two-way channel. ;-) > In general, the difference can be explained in the following terms: > > 1. When I signal before unlocking the mutex, I signal the state that I > know is true (because I own the mutex): "Hello, I did it and I know that > it's done". Again, this doesn't mean that the thread you wake up knows "it's done" when it finally gets control. > This may force the unnecessary context switch: waiting thread leaves the > condvar just to fall asleep on the mutex that it cannot lock. But there > is wait morph (or is there?). Maybe. Maybe not. > 2. When I signal after unlocking the mutex, I don't really know what I > signal, because the state of interest can be no longer true (because I > don't own the mutex and somebody else could have intercepted me): > "Hello, I did it, but I have no idea what happened from that time, so > what I'm telling you may be already false". One more time, this is ALWAYS true for the thread that wakes up, no matter what you knew when you signalled. > This may force the waiting thread(s) to wake up just to find out that > the condition is not true and fall back to wait on the condvar again. Yup. That's life in a concurrent world. But this is GOOD; because if the predicate is no longer true, it means the APPLICATION (and user) benefited by some other thread being able to process the condition earlier than the awakened thread could get through the scheduler, acquire the mutex, and so forth. Threads are cooperative, not competitive; it's the PROCESS throughput that matters. If you think of it that way, you'll get yourself into less trouble. (And avoid unnecessarily twisting your mental model.) That's one reason why thread-per-client is bad; it tries to force threads to COMPETE for resources, and they simply can't do that effectively -- they're inherently co-dependent because of the state they share. > I'm not really sure whether any of these two scenarios is inherently > ("generally") faster than the other, but the first scenarion sounds > better to me in terms of design logic. That's what I usually do. > > I might as well mix things up completely, so any explanation is welcome. ;-) -- Dave Butenhof, David.Butenhof@hp.com HP Utility Pricing software, POSIX thread consultant Manageability Solutions Lab (MSL), Hewlett-Packard Company 110 Spit Brook Road, ZK2/3-Q18, Nashua, NH 03062 .