I have this exercise of multithreading to solve. I have to create a class where 5 threads that wait each other and when the fifth arrives they are all unlocked. I would like to use mutex and condition variable but I don't know if I'm using them well. I create a class with the method add() that increment a variableX by 1, creates a thread that receives the function print() and later join() it. The function print() check if the variableX is minor of five, if it's like that the condition variable wait, else the condition variable wake up all the thread with the notify_all() function. The compiler gives 0 error, but with a debug I see that the program gets in a deadlock. Here is a snippet
#include "stdafx.h"
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
void print(mutex & mtx, condition_variable & convar, int x) {
if (x < 5){
unique_lock<mutex> lock(mtx); //acquire and lock the mutex
convar.wait(lock); //unlock mutex and wait
}
else {
convar.notify_all();
cout << "asdasd" << endl;
}
}
class foo {
public:
void add() {
this->x = x + 1;
thread t1(print, ref(mtx), ref(cv), x);
t1.join();
}
private:
mutex mtx;
condition_variable cv;
int x;
};
int main() {
foo f;
f.add();
f.add();
f.add();
f.add();
f.add();
}
Your function
void add() { this->x = x + 1; thread t1(print, ref(mtx), ref(cv), x); t1.join(); }
creates a single thread and then waits (join()
) till the thread ends. Since your thread function
void print(mutex & mtx, condition_variable & convar, int x) { if (x < 5){ unique_lock<mutex> lock(mtx); convar.wait(lock); // waits if x < 5 } // ...
and x
is presumable (you did fail to initialize it) < 5 you have your deadlock.
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
#include <condition_variable>
using namespace std;
void print(mutex & mtx, condition_variable & convar, int x)
{
if (x < 5) {
unique_lock<mutex> lock{ mtx };
convar.wait(lock);
} else {
convar.notify_all();
cout << "asdasd\n";
}
}
class foo {
private:
mutex mtx;
condition_variable cv;
int x{ 0 };
std::vector<thread> threads;
public:
void add() {
++x;
threads.push_back(thread(print, ref(mtx), ref(cv), x));
}
~foo() {
for (auto &t : threads)
t.join();
}
};
int main() {
foo f;
f.add();
f.add();
f.add();
f.add();
f.add();
}