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.
