条件变量不唤醒

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" 作为披萨列表对象本身的方法来实现可能是有意义的。