W
Willy Denoyette [MVP]
Jon,
Inline ***
Willy.
*** No, I didn't want to show inefficiency, I only wanted to illustrate the
"un-fairness" of the CLR when using Monitor classes as synchronization
mechanism, and I only wanted to warn OP and others about this behavior. And
note that you changed your mind only recently when you proposed the hybrid
solution (which is still somewhat inefficient be it less, unless you are
using a single lock per thread).
code, and after I illustrated the "un-fairness" when waiting on a common
SynchBloc (resulting in inefficiency when trying to make it behave like it
was "fair"), you said it was inefficient and you gave anough suggestions to
make it more efficient.
*** And what do you call a reasonable price?
*** I have a something similar using a single lock per thread, it works fine
on a single CPU box, but fails some time on a 4 way SMP box unless I pin
each thread to a specific CPU (using CPU mask).
induce a GC run (the CLR is prepared for this), suspending all managed
threads and doing some funny stuff with threads that are trying to return
from unmanaged land, and a GC run will re-order the Monitor wait queue in
the CLR (unles ther's only a single lock
).
starvation when not taking care when using Monitor methods to make threads
cooperate this way.
Monitor.Wait/Pulse/PulseAll doesn't
*** Agreed, but before I can make it reasonable fail-safe, I stick with
unmanaged code for this.
Willy.
Inline ***
Willy.
Jon Skeet said:I don't see why - you're making all your threads wait on a single
monitor when that's not necessary. Why is that a weak argument against
your code, when your code is trying to show inherent inefficiency?
*** No, I didn't want to show inefficiency, I only wanted to illustrate the
"un-fairness" of the CLR when using Monitor classes as synchronization
mechanism, and I only wanted to warn OP and others about this behavior. And
note that you changed your mind only recently when you proposed the hybrid
solution (which is still somewhat inefficient be it less, unless you are
using a single lock per thread).
*** No, you didn't, you only gave suggestions to OP before I posted theYes, I don't have the time to write a full example at the moment. I may
have by the end of the week - I've spent half of this evening clearing
out backlogs of news and mail (and haven't quite finished, but I'm
getting there). I think I gave enough suggestions to show that your
code wasn't the most efficient way to go.
code, and after I illustrated the "un-fairness" when waiting on a common
SynchBloc (resulting in inefficiency when trying to make it behave like it
was "fair"), you said it was inefficient and you gave anough suggestions to
make it more efficient.
They're a waste if you don't want the predictability. If you want the
predictability and are willing to pay a reasonably small price, it's
not a waste at all.
*** And what do you call a reasonable price?
You said more than that though - you said that trying to synchronize
threads in a fixed/predetermined order was highly inefficient or
impossible. I reckon it's feasible to make it only minorly inefficient
- at least for reasonable scenarios (where you don't have thousands of
threads).
*** I have a something similar using a single lock per thread, it works fine
on a single CPU box, but fails some time on a 4 way SMP box unless I pin
each thread to a specific CPU (using CPU mask).
*** Calling Wait requires you to own the SynchBlok, but calling Wait canI think we're talking at cross-purposes here. Calling Wait involves
entering a monitor first, and at that point there's a definite ordering
involved.
induce a GC run (the CLR is prepared for this), suspending all managed
threads and doing some funny stuff with threads that are trying to return
from unmanaged land, and a GC run will re-order the Monitor wait queue in
the CLR (unles ther's only a single lock

*** I have testcases running on large SMP boxes and I can simulate threadWell, you talked about a thread never waking up again - that was one of
the reasons you gave for it being impossible to write a mechanism for
releasing threads in the same order as they're suspended. If a thread
never wakes up when it should do (i.e. when it's runnable) that
suggests it's unreliable for general use - at least under the
conditions that prevent the thread from ever running
starvation when not taking care when using Monitor methods to make threads
cooperate this way.
Monitor.Wait/Pulse/PulseAll doesn't
provide it out of the box, but it can be built on top of them.
*** Agreed, but before I can make it reasonable fail-safe, I stick with
unmanaged code for this.
Willy.