Condition Mutexes
dsimcha
dsimcha at yahoo.com
Wed Oct 21 14:00:21 PDT 2009
== Quote from Steven Schveighoffer (schveiguy at yahoo.com)'s article
> On Wed, 21 Oct 2009 14:50:32 -0400, dsimcha <dsimcha at yahoo.com> wrote:
> > == Quote from Bartosz Milewski (bartosz-nospam at relisoft.com)'s article
> >> dsimcha Wrote:
> >> > void main() {
> >> > condition = new Condition( new Mutex() );
> >> > auto T = new Thread(&waitThenPrint);
> >> > T.start();
> >> > condition.notify(); // Never wakes up and prints FOO.
> >> > }
> >> Your program terminates immediately after sending the notification. You
> >> need to
> > stall the exit until the other thread has a chance to wake up.
> >
> > Thanks. I've implemented this, along w/ one other suggestion from
> > another poster.
> > Here's the new program. It still doesn't work.
> Here is a major flaw in your logic:
> A condition is a *signal* not a *flag*. In order to catch the signal you
> have to be listening for it. It's not like a semaphore.
> What you need in order to use a condition is a flag that is protected by
> the lock.
> Generally, the model is:
> thread1()
> {
> lock(mutex)
> {
> set(flag);
> condition.notify();
> }
> }
> thread2()
> {
> lock(mutex)
> {
> while(!flag)
> condition.wait();
> unset(flag); // we received the signal, clear it.
> }
> }
> The condition is basically a way to give control of waking up a thread to
> another thread. But the condition is not the, um... condition you are
> waiting for :) You still need a state variable to say "hey, you should
> continue now, the state is correctly set".
> Think of the flag like a mailbox flag. You only put it up *after* you put
> mail in the mailbox, and the mailman lowers the flag when he gets the mail
> out.
> There are lots of threading tutorials you can probably read to get it.
> But basically, I can break down what exactly happens, I'll do 2 scenarios:
> Scenario 1:
> 1. thread2 locks the mutex, which protects the flag. It sees that the
> flag is unset, so it waits on the condition. This *atomically* unlocks
> the mutex and enters the thread into the list of threads to wake up when
> the condition is signaled.
> 2. thread1 now can lock the mutex, and sets the flag. It notifies the
> condition, which wakes up thread2.
> 3. thread2 *remains asleep* until it can reacquire the lock. thread1
> unlocks the mutex after leaving the scope.
> 4. thread2 wakes up after reacquiring the mutex, and repeats the
> while-loop, seeing that the flag is now set.
> 5. thread2 unsets the flag and unlocks the mutex, continuing.
> Scenario 2:
> 1. thread1 locks the mutex.
> 2. thread2 sleeps because it cannot lock the mutex.
> 3. thread1 sets the flag, then signals the condition. Since nobody is
> listening *this doesn't affect anything*.
> 4. thread1 exits the scope, releasing the mutex.
> 5. thread2 now acquires the lock, sees the flag is set, and doesn't even
> wait on the condition, unsets the flag, exits the scope, and unlocks the
> mutex.
> You can see how the locking is important to protect the atomicity of
> setting the flag, and it is *really* important that the condition wait
> atomically unlocks the mutex and enters the thread into the condition's
> wakeup queue. So generally speaking: rule 1, don't do anything with a
> condition unless the mutex it uses is locked. rule 2, always have a state
> that is protected by the same lock that the condition is waiting with.
> You also may wonder why there is even a while loop, I mean, why recheck
> the flag after the condition is signalled? Well, in this case, it's not
> required, but it's very good practice. When you have a case where the
> flag is not a flag, but a multi-state variable, and you are waiting for a
> specific state, one thread might signal every time the state changes.
> Well, you don't want to continue until you get the state that you want, so
> you need to re-check the state. Another case is if you have several
> instances of thread2, and you only want to release one of them with the
> signal.
> Hope this helps.
> -Steve
Thank you. This was *extremely* helpful. I'll read over it in more detail when I
get back to hacking my futures/parallel foreach lib.
More information about the Digitalmars-d
mailing list