Understanding the example of using std::condition_variable
c++, c++11, multithreading
Solution
Yes, you are absolutely right: there is a (remote) possibility that the consumer thread will not start running until after `done` has been set. Further, the write to `done` in the producer thread and the read in the consumer thread produce a race condition, and the behavior is undefined. Same problem in your version. Wrap the mutex around the entire loop in each function. Sorry, don't have the energy to write the correct code.
Problem
There is example of using `condition_variable` taken from cppreference.com: ``` #include <condition_variable> #include <mutex> #include <thread> #include <iostream> #include <queue> #include <chrono> int main() { std::queue<int> produced_nums; std::mutex m; std::condition_variable cond_var; bool done = false; bool notified = false; std::thread producer([&]() { for (int i = 0; i < 5; ++i) { std::this_thread::sleep_for(std::chrono::seconds(1)); std::lock_guard<std::mutex> lock(m); std::cout << "producing " << i << '\n'; produced_nums.push(i); notified = true; cond_var.notify_one(); } std::lock_guard<std::mutex> lock(m); notified = true; done = true; cond_var.notify_one(); }); std::thread consumer([&]() { while (!done) { std::unique_lock<std::mutex> lock(m); while (!notified) { // loop to avoid spurious wakeups cond_var.wait(lock); } while (!produced_nums.empty()) { std::cout << "consuming " << produced_nums.front() << '\n'; produced_nums.pop(); } notified = false; } }); producer.join(); consumer.join(); } ``` If variable `done` comes `true` before the consumer thread is started, the consumer thread will not get any message. Indeed, `sleep_for(seconds(1))` almost avoids such situation, but could it be possible in theory (or if don't have `sleep` in code)? In my opinion correct version should look like this to force running consumer loop at least once: ``` std::thread consumer([&]() { std::unique_lock<std::mutex> lock(m); do { while (!notified || !done) { // loop to avoid spurious wakeups cond_var.wait(lock); } while (!produced_nums.empty()) { std::cout << "consuming " << produced_nums.front() << '\n'; produced_nums.pop(); } notified = false; } while (!done); }); ```