条件变量不唤醒
Conditional Variable doesn't wake up
我必须为一个学校项目用 C++ 构建一个比萨店。为此,我必须使用线程和 CondVar。我正在为 Condvar 这样做:
class Condvar
{
pthread_cond_t m_cond_var;
Mutex _mut;
public:
Condvar()
{
_mut.init();
pthread_cond_init(&m_cond_var, NULL);
}
~Condvar()
{
pthread_cond_destroy(&m_cond_var);
}
void wait()
{
_mut.lock();
pthread_cond_wait(&m_cond_var, _mut.getMutex());
_mut.unlock();
}
void signal()
{
pthread_cond_signal(&m_cond_var);
}
void broadcast()
{
pthread_cond_broadcast(&m_cond_var);
}
};
我厨房的建造者:
Kitchen::Kitchen(int nb_cooks, float mult, int time_ing):_nb_cooks(nb_cooks), _mult(mult), _time_ing(time_ing)
{
int i = 0;
_pipe = new PipeClass();
_fork = new Fork();
if (_fork->isSon())
{
_pipe->setSon(true);
_run = true;
_cond = new Condvar();
_stock.push_back(new Mushrooms(5));
cook_mutex.init();
ingr_mutex.init();
while (i < _nb_cooks)
{
_cooks.push_back(new Cook(mult, _pizzaList, *_cond, cook_mutex));
i++;
}
_thread = new Thread(this);
run();
}
else
_pipe->setSon(false);
}
我做我的披萨:
void Kitchen::doPizza()
{
PizzaGenerator gen;
std::string order;
APizza *pizza;
std::vector<AIngredient *>pizzaIngr;
bool check;
std::cout << "I do the pizza" << std::endl;
order = _pipe->getline();
pizza = gen.createForKitchen(order);
pizzaIngr = pizza->getIngredients();
if ((check = checkIngredients(pizzaIngr)) == false)
_pipe->write("KO");
else if (checkCooks() + _pizzaList.size() <= (unsigned int)(2 * _nb_cooks))
{
removeIngredientsFromStock(pizzaIngr);
_pizzaList.push_back(pizza);
std::cout << "JE RENTRE DEDANS" << std::endl;
_cond->signal();
_pipe->write("OK");
}
}
还有我的厨师 运行:
void *Cook::run()
{
while (!_stop)
{
if (_pizzaList.size() != 0)
std::cout << "I CAN COOK" << std::endl;
if (!_stop)
_cond.wait();
}
return NULL;
}
但是我的 condvar 没有起作用。
这个:
_mut.lock();
pthread_cond_wait(&m_cond_var, _mut.getMutex());
_mut.unlock();
从根本上误解了 pthreads 条件变量的工作原理。 pthread_cond_wait()
的 mutex 参数不只是用来装腔作势:条件变量必须与某个共享状态的条件配对(通常称为 predicate),并且传递的互斥量应该是保护该共享状态的互斥量。
换句话说,你应该使用 pthread_cond_wait()
非常像这样的东西:
pthread_mutex_lock(&mutex);
/* ... */
while (!condition)
pthread_cond_wait(&cond, &mutex);
/* 'condition' is now true, and mutex is held. Do some operation here that
* depends upon 'condition' being true. */
pthread_mutex_unlock(&mutex);
在这种情况下,看起来厨师们等待的条件可能是 "there is at least one pizza waiting to be cooked, or the stop flag has been set"。然后厨师们需要按照这些行调用代码:
pizzalist_mutex.lock();
do {
while (_pizzaList.size() == 0 && !stop)
pthread_cond_wait(&cond, pizzalist_mutex.getMutex());
if (_pizzaList.size() != 0)
{
/* remove pizza from pizza list */
pizzalist_mutex.unlock();
/* cook pizza */
pizzalist_mutex.lock();
}
} while (!stop);
pizzalist_mutex.unlock();
...其中 pizzalist_mutex
是一个互斥锁,用于保护 pizzaList 和全局 stop
。
将这个 "wait for a pizza from the pizza list" 作为披萨列表对象本身的方法来实现可能是有意义的。
我必须为一个学校项目用 C++ 构建一个比萨店。为此,我必须使用线程和 CondVar。我正在为 Condvar 这样做:
class Condvar
{
pthread_cond_t m_cond_var;
Mutex _mut;
public:
Condvar()
{
_mut.init();
pthread_cond_init(&m_cond_var, NULL);
}
~Condvar()
{
pthread_cond_destroy(&m_cond_var);
}
void wait()
{
_mut.lock();
pthread_cond_wait(&m_cond_var, _mut.getMutex());
_mut.unlock();
}
void signal()
{
pthread_cond_signal(&m_cond_var);
}
void broadcast()
{
pthread_cond_broadcast(&m_cond_var);
}
};
我厨房的建造者:
Kitchen::Kitchen(int nb_cooks, float mult, int time_ing):_nb_cooks(nb_cooks), _mult(mult), _time_ing(time_ing)
{
int i = 0;
_pipe = new PipeClass();
_fork = new Fork();
if (_fork->isSon())
{
_pipe->setSon(true);
_run = true;
_cond = new Condvar();
_stock.push_back(new Mushrooms(5));
cook_mutex.init();
ingr_mutex.init();
while (i < _nb_cooks)
{
_cooks.push_back(new Cook(mult, _pizzaList, *_cond, cook_mutex));
i++;
}
_thread = new Thread(this);
run();
}
else
_pipe->setSon(false);
}
我做我的披萨:
void Kitchen::doPizza()
{
PizzaGenerator gen;
std::string order;
APizza *pizza;
std::vector<AIngredient *>pizzaIngr;
bool check;
std::cout << "I do the pizza" << std::endl;
order = _pipe->getline();
pizza = gen.createForKitchen(order);
pizzaIngr = pizza->getIngredients();
if ((check = checkIngredients(pizzaIngr)) == false)
_pipe->write("KO");
else if (checkCooks() + _pizzaList.size() <= (unsigned int)(2 * _nb_cooks))
{
removeIngredientsFromStock(pizzaIngr);
_pizzaList.push_back(pizza);
std::cout << "JE RENTRE DEDANS" << std::endl;
_cond->signal();
_pipe->write("OK");
}
}
还有我的厨师 运行:
void *Cook::run()
{
while (!_stop)
{
if (_pizzaList.size() != 0)
std::cout << "I CAN COOK" << std::endl;
if (!_stop)
_cond.wait();
}
return NULL;
}
但是我的 condvar 没有起作用。
这个:
_mut.lock();
pthread_cond_wait(&m_cond_var, _mut.getMutex());
_mut.unlock();
从根本上误解了 pthreads 条件变量的工作原理。 pthread_cond_wait()
的 mutex 参数不只是用来装腔作势:条件变量必须与某个共享状态的条件配对(通常称为 predicate),并且传递的互斥量应该是保护该共享状态的互斥量。
换句话说,你应该使用 pthread_cond_wait()
非常像这样的东西:
pthread_mutex_lock(&mutex);
/* ... */
while (!condition)
pthread_cond_wait(&cond, &mutex);
/* 'condition' is now true, and mutex is held. Do some operation here that
* depends upon 'condition' being true. */
pthread_mutex_unlock(&mutex);
在这种情况下,看起来厨师们等待的条件可能是 "there is at least one pizza waiting to be cooked, or the stop flag has been set"。然后厨师们需要按照这些行调用代码:
pizzalist_mutex.lock();
do {
while (_pizzaList.size() == 0 && !stop)
pthread_cond_wait(&cond, pizzalist_mutex.getMutex());
if (_pizzaList.size() != 0)
{
/* remove pizza from pizza list */
pizzalist_mutex.unlock();
/* cook pizza */
pizzalist_mutex.lock();
}
} while (!stop);
pizzalist_mutex.unlock();
...其中 pizzalist_mutex
是一个互斥锁,用于保护 pizzaList 和全局 stop
。
将这个 "wait for a pizza from the pizza list" 作为披萨列表对象本身的方法来实现可能是有意义的。