多线程条件变量

Conditional Variables with multithreading

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

此代码有时有效,有时无效。首先,由于您没有提供完整的程序,这里是我用于测试目的的缺失部分:

#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);

这个调用只会唤醒一个线程。但是,哪个线程由 OS 自行决定。因此,如果它没有恰好唤醒应该唤醒的哲学家,则没有其他哲学家被唤醒。

一个简单的解决方法是唤醒所有等待的线程而不是一个。不匹配的哲学家会回去等待,下一个应该去的会去。

 pthread_cond_broadcast(&cond);

但是,由于每个线程都知道哪个哲学家应该醒来,您可以更改您的解决方案以实现这一点。一种方法是为每个哲学家实现一个单独的条件变量,并在下一个哲学家的条件变量上使用 pthread_cond_signal()