Question: For the solution to Too Much Milk suggested in the previous problem, each call to drinkMilkAndBuyIfNeeded() is atomic and holds the lock from the start to the end even if one roommate goes to the store. This solution is analogous to the roommate padlocking the Kitchen while going to the store, which seems a bit unrealistic. Implement a better solution to drinkMilkAndBuyIfNeeded () using both locks and condition variables. Since a roommate now needs to release the lock to the kitchen while going to the store, you will no longer acquire the lock at the start of this function and release it at the end. Instead, this function will call two helper-functions, each of which acquires/releases the lock. E.g.,
int
Kitchen : : drinkMilkAndBuyIfNeeded(){
int iShouldBuy = waitThenDrink();
if (iShouldBuy){
buyMilk();
}
}
In this function, waitThenDrink() should (if there is no milk) wait (using a condition variable) until there is milk, drink the milk, and if the milk is now gone, return a nonzero value to flag that the caller should buy milk. BuyMilk() should buy milk and then broadcast to let the waiting threads know that they can proceed. Again, test your code with varying numbers of threads.