具有多线程的条件变量

时间:2018-04-27 21:30:00

标签: c multithreading mutex condition-variable

我正在研究餐饮哲学家的问题,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,表示线程完成,并解锁互斥锁。

1 个答案:

答案 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()