This is an example of why multithreading is hard 

The Stack Overflow link from @cdunn2001 is good. It explains the concept better 
than me. I will try anyway:

You can't rely on all the threads being in a certain state at the same time. 
When you create those other threads in the creation loop, they start running on 
their own timeline. those threads are not guaranteed to have all gotten to the 
condition wait in their code by the time the main loop finishes.

If a thread isn't in the condition variable wait queue when the signal is 
called, it will never wake up, the signal calls are not "saved" in any way.

You "guaranteed" that all the threads are waiting on the condition variable 
wait queue by putting the sleep() call in. You basically gave the thread 
scheduler extra time to run all those other threads to the correct point.

* * *

> Do you mean that it is possible that I call signal from the main thread with, 
> say, two threads waiting on a Cond, then I call signal again from the main 
> thread on the same cond, if the scheduler does not context switch to one of 
> the two waiting thread between the two calls just one thread is woken up and 
> the second one remains waiting?

No, It's more subtle than that. A condition variable is just a queue of 
threads. A cond.wait(), push's the thread onto the queue. A cond.signal() pops 
a thread off the queue.

In the two threads waiting on a Cond example that you described, There are two 
threads on the queue, and two calls to cond.signal(), causing both threads to 
be popped off the queue. The key is that both threads are actually in the Cond 
queue, not "almost" in the Cond queue 

That's just the queue part, next you have the lock. Both threads are now awake, 
but both must "race" to win the lock. One thread will win the lock, and the 
other will lose, and be placed on the (different) queue waiting for the lock. 
(standard lock semantics) Which will work out just fine. No race condition or 
dead lock.

Reply via email to