pthread_cond_wait奇怪的行为

时间:2013-02-22 12:32:59

标签: c++ pthreads dining-philosopher

我正在尝试使用C ++解决Dining philosophers problem

使用g++ -lpthread编译代码。

整个解决方案都在philosophers github上。存储库包含两个cpp文件:main.cpp和philosopher.cpp。 “Main.cpp”创建互斥变量,信号量,5个条件变量,5个分叉,并启动哲学家。信号量仅用于同步哲学家的开端。其他参数传递给哲学家以解决问题。 “Philosopher.cpp”包含针对给定问题的解决方案,但在几个步骤之后发生死锁。

当哲学家0正在吃饭时发生僵局,而哲学家1(在他旁边)想要采取分叉。然后,哲学家1采取了互斥,并且不会回馈,直到哲学家0放下他的叉子。哲学家0不能因为采用互斥而放下他的叉子,所以我们陷入了僵局。问题出在 Philosopher :: take_fork方法中,调用pthread_cond_wait(a,b)不释放互斥锁b 。想不通为什么?

// Taking fork. If eather lef or right fork is taken, wait.
void Philosopher::take_fork(){
  pthread_mutex_lock(&mon);
  std::cout << "Philosopher " << id << " is waiting on forks" << std::endl;
  while(!fork[id] || !fork[(id + 1)%N])
    pthread_cond_wait(cond + id, &mon);
  fork[id] = fork[(id + 1)%N] = false;
  std::cout << "Philosopher " << id << " is eating" << std::endl;
  pthread_mutex_unlock(&mon);
}

请参考this code了解其余内容。

1 个答案:

答案 0 :(得分:1)

您对pthread_cond_wait()的电话很好,所以问题必须在其他地方。你有三个我可以看到的错误:

首先,在main()中,您只是初始化数组中的第一个条件变量。您需要初始化所有N条件变量:

for(int i = 0; i < N; i++) {
    fork[i] = true;
    pthread_cond_init(&cond[i], NULL);
}

pthread_mutex_init(&mon, NULL);

其次,在put_fork()中,您对其中一个条件变量的计算结果不正确:

pthread_cond_signal(cond + (id-1)%N);    /* incorrect */

id等于零时,(id - 1) % N等于-1,所以这将尝试发信号cond - 1,它不指向条件变量(这可能是指针实际上会破坏你的互斥锁,因为它可能直接放在堆栈上的cond之前。您真正想要的计算是:

pthread_cond_signal(cond + (id + N - 1) % N);

第三个错误不是导致死锁的原因,但每次拨打srand(time(NULL))时都不应致电rand() - 只需在main()开始时拨打一次