我正在尝试使用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了解其余内容。
答案 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()
开始时拨打一次