Here is my code:
Class
class carl{
public:
int x = 0;
std::mutex _mu;
std::condition_variable cond;
bool donecreating = false;
void createFood(){
if(x == 0){
std::unique_lock<mutex> locker(_mu);
x++;
std::cout<<"creating food.."<<std::endl;
cout<<"Food count: "<<x<<endl;
locker.unlock();
cond.notify_one(); //notify
std::this_thread::sleep_for(chrono::seconds(1)); //sleep
}
}
void eatFood(){
std::unique_lock<mutex> locker(_mu); //lock
std::cout<<"i am executing"<<std::endl; //notif
cond.wait(locker); //wait
x--; //process food
std::cout<<"eating food.."<<std::endl;
cout<<"Food left: "<<x<<endl;
locker.unlock();
}
};
Function aka thread one
void create(carl& carl){
for(int i=0;i>-100;i--){ //create 100 times
carl.createFood();
}
carl.donecreating = true; //done creating 100 food
}
Main
int main(int argc, char** argv) {
carl c; //init object
std::thread t1(create,std::ref(c)); //init thread
while(c.donecreating != true){ //exit condition is if the class is done creating food 100 times
c.eatFood();
}
t1.join();
return 0;
}
Output:
i am executing
creating food...
Food count: 1
eating food..
Food left: 0
I am trying to trace my code and here is my understanding so far and i need some clarifications
1.) Upon compile, main thread(consumer) is faster than the producer thread so it is fired up first and was put to sleep by cond.wait(locker);
to prevent it from eating because no food was made yet. but before cond.wait(locker);
there is std::unique_lock<mutex> locker(_mu);
, is it automatically unlocked so that the other thread can access it while waiting?
2.) If ever the createFood
was fired up first(because threads are processor based? it's possible right?), it will send the cond.notify_one();
if there is one and if not then it will just simply go on creating a food and then sleep
. The other thread will start processing because the mutex
will be unlocked then it will reach cond.wait(locker);
but there is a food already so sleep
won't be necessary the solution that i found out is by implementing spurious wake
, is that what it is for?
3.) I'm still really curious about std::unique_lock<mutex> locker(_mu);
like what really happens if the other thread reached that line of code and it's currently locked? does it ignore every line below that and just move on until that block of code gets out of scope? or does it stops on that line and wait until it gets unlocked?
To start with, your code has a data race (and hence undefined behavior) since if(x == 0)
in createFood()
accesses x
unprotected. Every access to x
, both reads and writes, must be protected by the mutex.
is it automatically unlocked so that the other thread can access it while waiting?
Yes, wait()
unlocks the mutex before blocking on the condition variable, and then locks the mutex again before it returns.
The other thread will start processing because the mutex will be unlocked then it will reach
cond.wait(locker);
but there is a food already so sleep won't be necessary the solution that i found out is by implementing spurious wake, is that what it is for?
No, spurious wakeup is not something you have control over. Your code has two problems:
eatFood()
can end spuriously, in which case there isn't actually any food to eat, but you don't handle this case either. The solution is to run wait
in a loop, until there is food available. This is equivalent to running the version of wait
taking a predicate:
while(x == 0) cond.wait(locker);
or
cond.wait(locker, [this](){ return x > 0; });
I'm still really curious about
std::unique_lock<mutex> locker(_mu);
like what really happens if the other thread reached that line of code and it's currently locked? does it ignore every line below that and just move on until that block of code gets out of scope? or does it stops on that line and wait until it gets unlocked?
The latter. After that line, the mutex is locked by the thread constructing locker
. This means blocking and waiting if necessary.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.