0

我正在尝试使用 C++解决餐饮哲学家的问题。

代码用g++ -lpthread.

整个解决方案在哲学家 github 上。Repository 包含两个 cpp 文件:main.cpp 和philosopher.cpp。“Main.cpp”创建互斥变量、信号量、5 个条件变量、5 个分叉,并启动哲学家。信号量仅用于同步哲学家的启动。其他参数被传递给哲学家来解决问题。“Philosopher.cpp”包含给定问题的解决方案,但经过几步就会发生死锁。

当哲学家 0 正在吃饭,而哲学家 1(在他旁边)想拿叉子时,就会发生死锁。然后,哲学家 1 拿走了互斥锁,直到哲学家 0 放下他的叉子才把它还给它。由于采取了互斥锁,哲学家 0 不能放下他的叉子,所以我们陷入了僵局。问题出在Philosopher::take_fork 方法中,调用 pthread_cond_wait(a,b) 没有释放 mutex 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);
}

其余的请参考此代码

4

1 回答 1

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().

于 2013-02-25T05:45:01.907 回答