Variable Status Deadlock

I have a dead end problem in my code related to using condition variables. This is more a design issue than a clean code issue. I have no problem writing code as soon as I understand the correct design. I have the following script:

  • Thread A expects a condition variable.
  • Thread B calls notify_all, and thread A wakes up.

This, of course, is what I want, and what happens when everything works as expected. But sometimes I get the following script:

  • Thread A executes the code just before it starts waiting for the condition variable.
  • Thread B calls notify_all, assuming thread A is waiting.
  • Thread A begins to wait for the condition variable, not realizing that thread B has already told it to stop waiting. Dead end.

What is the best way to solve this problem? I can't think of a reliable way to check if thread A is really waiting to find out when I should call notify_all on thread B. Do I need to resort to timed_lock? I would like.

+6
source share
2 answers

In the period before Thread A expects a condition variable, it must contain a mutex. The easiest solution is to make sure that Thread B has the same mutex at the time it calls notify_all. So something like this:

std::mutex m; std::condition_variable cv; int the_condition = 0; Thread A: { std::unique_lock<std::mutex> lock(m); do something while (the_condition == 0) { cv.wait(lock); } now the_condition != 0 and thread A has the mutex do something else } // releases the mutex; Thread B: { std::unique_lock<std::mutex> lock(m); do something that makes the_condition != 0 cv.notify_all(); } // releases the mutex 

This ensures that Thread B will execute notify_all () only before Thread A receives the mutex or while Thread A expects a condition variable.

Another key here, however, is the while loop, which expects the condition to become true. After A has a mutex, it should not be possible for any other thread to change the condition until A checks the_condition, finds it false and starts to wait (thus freeing up the mutex).

The fact is that you really expect the_condition to become non-zero, std :: condition_variable :: notify_all just tells you that thread B believes that thread A should wake up and test.

+5
source

The state variable should always be associated with the mutex in order to avoid the race condition created by one thread preparing to wait and another thread that can signal the state before the first thread actually waits for it, which leads to a deadlock. The stream will constantly wait for a signal that is never sent. Any mutex can be used; there is no explicit connection between the mutex and the condition variable.

+2
source

All Articles