3

I'm trying to understand the flow of the condition_variable when I have more than one thread waiting to execute. To my understanding, all threads would try to grab the unique lock, one would get it and then progress to the wait(), if you call notify_all, wouldn't there at most be one thread waiting that would be allowed through. Until it releases it's lock and allows the other threads through.

Does the cv communicate with the unique lock and let all threads through all at once? If so is it truly all at once or do the threads sequentially pass through one after another.

std::condition_variable cv;
std::mutex cv_m; // This mutex is used for three purposes:
                 // 1) to synchronize accesses to i
                 // 2) to synchronize accesses to std::cerr
                 // 3) for the condition variable cv
int i = 0;

void waits()
{
    std::unique_lock<std::mutex> lk(cv_m);
    std::cerr << "Waiting... \n";
    cv.wait(lk, []{return i == 1;});
    std::cerr << "...finished waiting. i == 1\n";
}

http://en.cppreference.com/w/cpp/thread/condition_variable/notify_all

Joshua Waring
  • 619
  • 7
  • 23

2 Answers2

3

When you call wait (the one-argument version) the lock is unlocked and the thread enter a wait-state until the CV is "notified". When a thread wakes up the lock is locked again.

When you call notify_one, basically a random thread waiting on the CV will be notified. When you call notify_all all threads waiting on the CV will be woken up from the wait-state, and the first that locks the lock will be the one that continues. Which that will be is also random.

Note that when I say "random", the actual implementation of threads (from the C++ library down to the operating system kernel and maybe even the hardware) on your system may be implemented in a way to make it possible to infer which thread will be the one that wakes up and gets the lock, but from the point of view of us application writers who uses condition variables, there's no predetermined order, it's random.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    So the first one that grab the lock get's through the wait, until it releases it's lock. So they're allowed through sequentially instead of all at once. Thank you – Joshua Waring Sep 25 '15 at 07:34
  • 1
    @JoshuaWaring It worth mentioning that unlock and entering wait state (inside `wait`) are required to happen atomically. – Ivan Aksamentov - Drop Sep 25 '15 at 07:58
  • 1
    For completeness, most POSIX implementations allow for spurious wakeup which means in rare cases (more often under heavy contention), `notify_one` can wake up more than one thread. More precisely, the POSIX example implementation allows the underlying function `pthread_cond_signal` to wake up one waiting thread and any number of threads that were *just about* to start waiting. Therefore even with a single `notify_one` to do a particular task, it's still necessary to e.g. lock a mutex. – Arne Vogel Sep 25 '15 at 09:44
2

While the threads do have to call wait one at a time, while they're waiting, they don't hold the lock. So additional threads can get through to the wait function.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278