我正在研究餐饮哲学家的问题,n哲学家轮流思考和饮食。我希望有一个版本的哲学家将按照他们的id:0,1,2,3,4 ...的顺序吃,但我的线程一直被阻止。我的帖子首先调用PhilosopherThread
()。
void putDownChopsticks(int threadIndex){
//finished eating
pindex++;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
void pickUpChopsticks(int threadIndex){
pthread_mutex_lock(&lock);
while(pindex != threadIndex){
pthread_cond_wait(&cond, &lock);
}
//lets go eat
}
void eating(){
//put thread to sleep
}
void thinking(){
//put thread to sleep
}
void* PhilosopherThread(void *x){
int *index = x;
thinking(); //just puts thread to sleep to simulate thinking
pickUpChopsticks(*index);
eating(); //just puts thread to sleep to simulate eating
putDownChopsticks(*index);
return NULL;
}
我在试图让哲学家井然有序时遇到了一些麻烦。在线程被阻塞之前,我只能获得前2个线程。
编辑:据我所知,我这样做是对的。我首先锁定互斥锁,然后检查pindex是否是当前的线程id,如果不是线程将等到pindex确实等于id。然后线程可以吃掉,一旦完成,我们会增加pindex,表示线程完成,并解锁互斥锁。
答案 0 :(得分:2)
此代码有时有效,有时则无效。首先,由于您没有提供完整的程序,以下是我用于测试目的的缺失位:
#include <stdlib.h>
#include <pthread.h>
static pthread_cond_t cond;
static pthread_mutex_t lock;
static pindex;
/* ... your code ... */
int main () {
int id[5], i;
pthread_t tid[5];
for (i = 0; i < 5; ++i) {
id[i] = i;
pthread_create(tid+i, 0, PhilosopherThread, id+i);
}
for (i = 0; i < 5; ++i) pthread_join(tid[i], 0);
exit(0);
}
要注意的关键是你如何唤醒下一位哲学家:
pthread_cond_signal(&cond);
此调用只会唤醒一个线程。但是,哪个线程由操作系统自行决定。因此,如果没有发生唤醒应该醒来的哲学家,那么其他任何哲学家都不会被唤醒。
一个简单的解决方法是唤醒所有等待的线程而不是一个。那些不匹配的哲学家会回去等待,而下一个应该去的人将会去。
pthread_cond_broadcast(&cond);
然而,由于每个线程都知道哪个哲学家应该醒来,你可以改变你的解决方案以允许这种情况发生。一种方法是为每个哲学家实现一个单独的条件变量,并在下一个哲学家的条件变量上使用pthread_cond_signal()
。