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