I'm pretty new to C++ and I'm experimenting with some concurrency in C++ using threadpooling, condition variables, locks and mutex. The program is in essence a bunch threads of two categories sharing a common resource. Metaphorically, there are wolves and sheep, sharing a waterhole, and they can't be around the waterhole at the same time. Multiple sheeps or multiple wolves can however be there at the same time.
The threads are managed by a class called Waterhole, which holds a mutex, a condition variable and two integers which are supposed to keep track of how many wolves or sheep there are around the waterhole. There are also 4 methods which are for the entering/exiting of each animal. Here is my class:
class Waterhole {
private:
int wolfInside;
int sheepInside;
mutex my_mutex;
condition_variable CONVAR;
public:
void WolfEnters() {
cout<<"A wolf enters the watercave\n"<<endl;
unique_lock<mutex> lock(my_mutex);
CONVAR.wait(lock, [this]{return sheepInside == 0;});
wolfInside+=1;
}
void WolfLeaves() {
cout<<"Wolf has finished drinking and is leaving the watercave\n";
my_mutex.lock();
wolfInside -= 1;
CONVAR.notify_all();
}
void SheepEnters(){
unique_lock<mutex> lock(my_mutex);
cout<<"A Sheep enters the watercave\n";
CONVAR.wait(lock, [this]{return wolfInside == 0;});
sheepInside+=1;
};
void SheepLeaves() {
cout<<"sheep has finished drinking and is leaving the watercave";
my_mutex.lock();
sheepInside-=1;
CONVAR.notify_all();
}
};
Here is the description of each thread, i.e wolves and sheeps:
void sheep(Waterhole &waterhole) {
int i = 0;
while(i++ < SIM){
this_thread::sleep_for(chrono::milliseconds(100));
cout<<"Sheep is thirsty\n";
waterhole.SheepEnters();
this_thread::sleep_for(chrono::milliseconds(1));
waterhole.SheepLeaves();
}
}
void wolf(Waterhole &waterhole) {
int i = 0;
while(i++ < SIM){
this_thread::sleep_for(chrono::milliseconds(100));
cout<<"Wolf is thirsty\n";
waterhole.WolfEnters();
this_thread::sleep_for(chrono::milliseconds(1));
waterhole.WolfLeaves();
}
}
And finally here is my main method which creates and starts all threads:
int main() {
vector<thread> threadvec;
Waterhole waterhole;
int nrSheep = 2;
int nrWolf = 2;
for (int i = 0; i < nrSheep; i++) {
threadvec.push_back(move(thread(sheep, ref(waterhole))));
}
for (int i = 0; i < nrWolf; i++) {
threadvec.push_back(move(thread(wolf,ref(waterhole))));
}
for (int i = 0; i < nrSheep; i++) {
threadvec[i].join();
}
for (int i = 0; i < nrWolf; i++) {
threadvec[i].join();
}
return 0;
}
Now to the problem at hand. Nor the Wolfs or the sheep ever leaves the waterhole. They are just able to enter!
Here is the output of the program:
Sheep is thirsty
Wolf is thirsty
Wolf is thirsty
Sheep is thirsty
A Sheep enters the watercave
A Wolf enters the watercave
A Wolf enters the watercave
A Sheep enters the watercave
And after this the program never terminates, which is intended since I don't kill any threads in my program, but I believe that after the enter-methods, something with the locks and condition variables don't add upp.
I have googled this extensively and can't find anything similiar of what I'm trying to do. I believe that the output looks like this because of a deadlock.
Thanks in advance!
Aucun commentaire:
Enregistrer un commentaire