mardi 31 octobre 2023

Use C++11 condition_varible to make 3 threads print 1-100 in turns. But the dead lock confuses me

I want to write a program use 3 threads to print 1-100 in turns using C++11 condition_variable, but dead lock confused me, here are my code:

the tmp.cpp is:

#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>


std::condition_variable cv12;
std::condition_variable cv23;
std::condition_variable cv31;

std::mutex mtx;

void Print(int i) {
  while (i <= 100) {
    if (i % 3 == 1) {
      {
        std::unique_lock<std::mutex> l(mtx);
        cv31.wait(l);
        std::cout << i << std::endl;
      }

      cv12.notify_all();
    } else if (i % 3 == 2) {
      {
        std::unique_lock<std::mutex> l(mtx);
        cv12.wait(l);
        std::cout << i << std::endl;
      }

      cv23.notify_all();
    } else if (i % 3 == 0) {
      {
        std::unique_lock<std::mutex> l(mtx);
        cv23.wait(l);
        std::cout << i << std::endl;
      }

      cv31.notify_all();
    }
    i += 3;
  }
}

int main() {
  std::thread t1(Print, 1);
  std::thread t2(Print, 2);
  std::thread t3(Print, 3);

  cv31.notify_all();

  t1.join();
  t2.join();
  t3.join();

  return 0;
}

the run command is:

$ g++ -g -o tmp tmp.cpp  && ./tmp

But the output sometimes could just and stops.

╰─$ ./tmp                
1
2
    

When I ask GPT or Claud, they give me no advice, that imply my code may correct, when I use gdb to debug for the deadlock, but this program always run correctly in gdb, which dead lock never occurs.

I refer to the ways of condition varible wait usage, may should add a Predicate, but I don't want to write more global varible to handle this, and I find the Predicate is optional, so I don't know where is the bug in my code?

Aucun commentaire:

Enregistrer un commentaire