Home > Enterprise >  How condition_variable comes to deadlock
How condition_variable comes to deadlock

Time:09-13

I write a demo about condition_variable. I need the correct order to be first-second-third, but there comes to the deadlock.Program infinite loop and there is no output.

class Foo
{
public:
  void printfirst() { printf("first"); }
  void printsecond() { printf("second"); }
  void printthird() { printf("third"); }
  Foo()
  {
  }
  mutex mtx;
  condition_variable cv1, cv2;

  void first()
  {
    lock_guard<mutex> l(mtx);
    printfirst();
    cv1.notify_one();
  }

  void second()
  {
    unique_lock<mutex> ul(mtx);
    cv1.wait(ul);
    printsecond();
    cv2.notify_one();
  }
  void third()
  {
    unique_lock<mutex> ul(mtx);
    cv2.wait(ul);
    printthird();
  }
};

when i add two var (firstready and secondready) and invoke the condition_variable.wait(lock,function()), there is no error. whats the difference of these two function?

class Foo
{
public:
  void printfirst() { printf("first"); }
  void printsecond() { printf("second"); }
  void printthird() { printf("third"); }
  Foo()
  {
    firstready=false;
    secondready=false;
  }
  mutex mtx;
  bool firstready,secondready;
  condition_variable cv1, cv2;

  void first()
  {
    lock_guard<mutex> l(mtx);
    printfirst();
    firstready=true;
    cv1.notify_one();
  }

  void second()
  {
    unique_lock<mutex> ul(mtx);
    cv1.wait(ul,[&]{return firstready;});
    printsecond();
    secondready=true;
    cv2.notify_one();
  }
  void third()
  {
    unique_lock<mutex> ul(mtx);
    cv2.wait(ul,[&]{return secondready;});
    printthird();
  }
};

CodePudding user response:

The first code may deadlock because, for example, cv2 might be notified before third starts running. The condition variable doesn't remember that you notified it. If nobody is waiting when you notify it, nothing happens.

The second code remembers that the notification was sent. It only waits if secondready is false, otherwise it doesn't wait. The variable secondready remembers that the condition variable was notified.

The second code is the proper way to use a condition variable. A condition variable is designed so you can wait for almost any condition, e.g. !queue.is_empty() && pi > 3. That's why the condition variable doesn't remember whether the condition is true - it doesn't know what the condition is - that's your job.

  • Related